/// <summary> /// 引数の解決。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="argsInfo">引数情報。</param> /// <param name="args">引数。</param> /// <param name="argTypes">引数の型。</param> internal static void ResolveArgs(VarPool varManager, object[] argsInfo, out object[] args, out Type[] argTypes) { args = new object[argsInfo.Length]; argTypes = new Type[argsInfo.Length]; for (int i = 0; i < argsInfo.Length; i++) { VarAddress handle = argsInfo[i] as VarAddress; //値の場合 if (handle == null) { args[i] = argsInfo[i]; if (args[i] != null) { argTypes[i] = args[i].GetType(); } } //変数の場合は登録されているオブジェクトに変換 else { VarAndType varAndType = varManager.GetVarAndType(handle); args[i] = varAndType.Core; argTypes[i] = varAndType.Type; } } }
/// <summary> /// 呼び出し対象の解決。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="typeFinder">タイプ検索。</param> /// <param name="info">呼び出し情報。</param> /// <param name="type">タイプ。</param> /// <param name="targetObj">オブジェクト。</param> /// <param name="args">引数。</param> /// <param name="argTypes">引数タイプ。</param> /// <param name="bind">バインディング。</param> static void ResolveInvokeTarget(VarPool varManager, TypeFinder typeFinder, ProtocolInfo info, out Type type, out object targetObj, out object[] args, out Type[] argTypes, out BindingFlags bind) { type = null; targetObj = null; bind = BindingFlags.Public | BindingFlags.NonPublic; //static呼び出し時 if (info.VarAddress == null) { type = typeFinder.GetType(info.TypeFullName); if (type == null) { throw new InformationException(string.Format(CultureInfo.CurrentCulture, ResourcesLocal.Instance.UnknownTypeInfoFormat, info.TypeFullName)); } bind |= BindingFlags.Static; } //オブジェクトに対する呼び出し else { VarAndType varAndType = varManager.GetVarAndType(info.VarAddress); targetObj = varAndType.Core; if (targetObj == null) { throw new InformationException(ResourcesLocal.Instance.NullObjectOperation); } type = varAndType.Type; bind |= BindingFlags.Instance; } //引数の解決 ResolveArgs(varManager, info.Arguments, out args, out argTypes); }
/// <summary> /// 処理呼び出し。 /// </summary> /// <param name="async">非同期実行用。</param> /// <param name="varManager">変数管理。</param> /// <param name="typeFinder">タイプ検索。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> internal static ReturnInfo Execute(IAsyncInvoke async, VarPool varManager, TypeFinder typeFinder, ProtocolInfo info) { switch (info.ProtocolType) { case ProtocolType.AsyncResultVarInitialize: case ProtocolType.VarInitialize: return(VarInitialize(varManager, info)); case ProtocolType.VarNew: return(VarNew(varManager, typeFinder, info)); case ProtocolType.BinOff: return(BinOff(varManager, info)); case ProtocolType.GetValue: return(GetValue(varManager, info)); case ProtocolType.SetValue: return(SetValue(varManager, info)); case ProtocolType.GetElements: return(GetElements(varManager, info)); case ProtocolType.AsyncOperation: return(AsyncOperation(async, varManager, typeFinder, info)); case ProtocolType.IsEmptyVar: return(IsEmptyVar(varManager, info)); default: throw new InternalException(); } }
/// <summary> /// 値取得処理呼び出し。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo GetValue(VarPool varManager, ProtocolInfo info) { //引数の数は0であること if (info.Arguments.Length != 0) { throw new InternalException(); } return(new ReturnInfo(varManager.GetVarAndType(info.VarAddress).Core)); }
/// <summary> /// 呼び出し後の引数反映。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="argsInfo">引数情報。</param> /// <param name="args">引数。</param> internal static void ReflectArgsAfterInvoke(VarPool varManager, object[] argsInfo, object[] args) { if (argsInfo.Length != args.Length) { throw new InternalException(); } for (int i = 0; i < argsInfo.Length; i++) { VarAddress handle = argsInfo[i] as VarAddress; if (handle != null) { varManager.SetObject(handle, args[i]); } } }
/// <summary> /// 変数初期化。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo VarInitialize(VarPool varManager, ProtocolInfo info) { //初期化は引数は1であること。 if (info.Arguments.Length != 1) { throw new InternalException(); } //引数の解決 object[] args; ResolveArgs(varManager, info.Arguments, out args); //変数登録 return(new ReturnInfo(varManager.Add(args[0]))); }
/// <summary> /// 存命登録解除。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="arguments">引数情報。</param> /// <param name="handle">戻り値ハンドル。</param> static void FreeKeepAlive(VarPool varManager, object[] arguments, VarAddress handle) { if (handle != null) { varManager.FreeKeepAlive(handle); } for (int i = 0; i < arguments.Length; i++) { VarAddress aliveHandle = arguments[i] as VarAddress; if (aliveHandle != null) { varManager.FreeKeepAlive(aliveHandle); } } }
/// <summary> /// 値設定処理呼び出し。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo SetValue(VarPool varManager, ProtocolInfo info) { //引数の数は1であること if (info.Arguments.Length != 1) { throw new InternalException(); } //引数の解決 object[] args; ResolveArgs(varManager, info.Arguments, out args); //値の設定 varManager.SetObject(info.VarAddress, args[0]); return(new ReturnInfo()); }
/// <summary> /// メソッドorプロパティー実行。 /// </summary> /// <param name="async">非同期実行用。</param> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <param name="obj">実行対象オブジェクト。</param> /// <param name="args">操作実行引数。</param> /// <param name="method">メソッド情報。</param> /// <returns>戻り情報。</returns> static ReturnInfo ExecuteMethodOrProperty(IAsyncInvoke async, VarPool varManager, ProtocolInfo info, object obj, object[] args, MethodInfo method) { //戻り値 VarAddress handle = null; if (method.ReturnParameter.ParameterType != typeof(void)) { handle = varManager.Add(null); } //番号管理から消されないようにする KeepAlive(varManager, info.Arguments, handle); //非同期実行 async.Execute(delegate { ReturnInfo retInfo = new ReturnInfo(); try { object retObj = method.Invoke(obj, args); if (method.ReturnParameter.ParameterType != typeof(void)) { varManager.SetObject(handle, retObj); } //ref, outの解決 List <object> retArgsTmp = new List <object>(); retArgsTmp.Add(null); //完了通知変数を戻す。しかし、ここではまだ格納しない retArgsTmp.AddRange(args); ReflectArgsAfterInvoke(varManager, info.Arguments, retArgsTmp.ToArray()); } catch (Exception e) { retInfo = new ReturnInfo(new ExceptionInfo(e)); } //完了通知 varManager.SetObject((VarAddress)info.Arguments[0], retInfo); //存命状態を解く FreeKeepAlive(varManager, info.Arguments, handle); }); return(new ReturnInfo(handle)); }
/// <summary> /// 内部要素取得処理呼び出し。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo GetElements(VarPool varManager, ProtocolInfo info) { //変数の解決 object obj = varManager.GetVarAndType(info.VarAddress).Core; //この処理が可能なのはIEnumerableを継承している場合 IEnumerable enumerable = obj as IEnumerable; if (enumerable == null) { throw new InformationException(ResourcesLocal.Instance.HasNotEnumerable); } //要素をすべて変数登録 List <VarAddress> list = new List <VarAddress>(); foreach (object element in enumerable) { list.Add(varManager.Add(element)); } return(new ReturnInfo(list.ToArray())); }
/// <summary> /// 引数の解決。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="argsInfo">引数情報。</param> /// <param name="args">引数。</param> internal static void ResolveArgs(VarPool varManager, object[] argsInfo, out object[] args) { Type[] argTypes; ResolveArgs(varManager, argsInfo, out args, out argTypes); }
/// <summary> /// 空の変数であるか /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo IsEmptyVar(VarPool varManager, ProtocolInfo info) { return(new ReturnInfo(varManager.IsEmptyVar((VarAddress)info.Arguments[0]))); }
/// <summary> /// フィールド操作実行。 /// </summary> /// <param name="async">非同期実行用。</param> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <param name="obj">実行対象オブジェクト。</param> /// <param name="args">操作実行引数。</param> /// <param name="field">フィールド情報。</param> /// <returns>戻り情報。</returns> static ReturnInfo ExecuteField(IAsyncInvoke async, VarPool varManager, ProtocolInfo info, object obj, object[] args, FieldInfo field) { //get if (args.Length == 0) { //戻り値格納用 VarAddress getVar = varManager.Add(null); //番号管理から消されないようにする KeepAlive(varManager, info.Arguments, getVar); //非同期実行 async.Execute(delegate { ReturnInfo retInfo = new ReturnInfo(); try { varManager.SetObject(getVar, field.GetValue(obj)); } catch (Exception e) { retInfo = new ReturnInfo(new ExceptionInfo(e)); } //完了通知 varManager.SetObject((VarAddress)info.Arguments[0], retInfo); //存命状態を解く FreeKeepAlive(varManager, info.Arguments, getVar); }); return(new ReturnInfo(getVar)); } //set else if (args.Length == 1) { //番号管理から消されないようにする KeepAlive(varManager, info.Arguments, null); //非同期実行 async.Execute(delegate { ReturnInfo retInfo = new ReturnInfo(); try { field.SetValue(obj, args[0]); } catch (Exception e) { retInfo = new ReturnInfo(new ExceptionInfo(e)); } //完了通知 varManager.SetObject((VarAddress)info.Arguments[0], retInfo); //存命状態を解く FreeKeepAlive(varManager, info.Arguments, null); }); return(new ReturnInfo()); } throw new InternalException(); }
/// <summary> /// 実行名称と引数によって実施するオペレーションを判断する。 /// 非同期実行部分以外のコードはスレッドセーフでなければならない。 /// </summary> /// <param name="async">非同期実行用。</param> /// <param name="varManager">変数管理。</param> /// <param name="typeFinder">タイプ検索。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo AsyncOperation(IAsyncInvoke async, VarPool varManager, TypeFinder typeFinder, ProtocolInfo info) { Type type; object obj; object[] args; Type[] argTypesOri; BindingFlags bind; //実行対象の解決 ResolveInvokeTarget(varManager, typeFinder, info, out type, out obj, out args, out argTypesOri, out bind); //第一引数は完了時結果格納変数 List <object> argTmp = new List <object>(args); argTmp.RemoveAt(0); args = argTmp.ToArray(); List <Type> argTypeTmp = new List <Type>(argTypesOri); argTypeTmp.RemoveAt(0); argTypesOri = argTypeTmp.ToArray(); //操作解決用型情報取得 if (info.OperationTypeInfo != null) { type = typeFinder.GetType(info.OperationTypeInfo.Target); if (type == null) { throw new InformationException(string.Format(CultureInfo.CurrentCulture, ResourcesLocal.Instance.UnknownTypeInfoFormat, info.OperationTypeInfo.Target)); } } //操作名称最適化 string operation = OptimizeOperationName(type, info.Operation, args.Length); Type findStartType = type; //引数の型を取得 Type[] argTypes = GetArgTypes(typeFinder, info.OperationTypeInfo, argTypesOri); //操作検索 bool isObjectArrayArg = false; int nameMatchCount = 0; bool first = true; bool isAmbiguousArgs = false; while (!isAmbiguousArgs && type != null) { //親の型へ。 if (!first) { type = type.BaseType; if (type == null) { break; } } first = false; //フィールド FieldInfo field = FindField(type, bind, operation, args, ref isObjectArrayArg, ref nameMatchCount); if (field != null) { return(ExecuteField(async, varManager, info, obj, args, field)); } //プロパティーとメソッド MethodInfo method = FindMethodOrProperty(info.OperationTypeInfo != null, type, bind, operation, argTypes, ref isObjectArrayArg, ref nameMatchCount, ref isAmbiguousArgs); if (method != null) { return(ExecuteMethodOrProperty(async, varManager, info, obj, args, method)); } } //結局発見できなかった。 throw MakeNotFoundException(info, findStartType, argTypes, isObjectArrayArg, nameMatchCount, isAmbiguousArgs); }
/// <summary> /// 変数破棄。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo BinOff(VarPool varManager, ProtocolInfo info) { varManager.Remove(info.VarAddress); return(new ReturnInfo()); }
/// <summary> /// 生成処理呼び出し。 /// </summary> /// <param name="varManager">変数管理。</param> /// <param name="typeFinder">タイプ検索。</param> /// <param name="info">呼び出し情報。</param> /// <returns>戻り値情報。</returns> static ReturnInfo VarNew(VarPool varManager, TypeFinder typeFinder, ProtocolInfo info) { //処理可能な型であるか判断 Type type = typeFinder.GetType(info.TypeFullName); if (type == null) { throw new InformationException(string.Format(CultureInfo.CurrentCulture, ResourcesLocal.Instance.UnknownTypeInfoFormat, info.TypeFullName)); } //引数の解決 object[] args; Type[] argTypesOri; ResolveArgs(varManager, info.Arguments, out args, out argTypesOri); Type[] argTypes = GetArgTypes(typeFinder, info.OperationTypeInfo, argTypesOri); //引数が0でかつ値型の場合 if (argTypes.Length == 0 && type.IsValueType) { //変数登録 return(new ReturnInfo(varManager.Add(Activator.CreateInstance(type)))); } //オーバーロードの解決 ConstructorInfo[] constructorInfos = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); List <ConstructorInfo> constructorList = new List <ConstructorInfo>(); bool isObjectArrayArg = false; for (int i = 0; i < constructorInfos.Length; i++) { ParameterInfo[] paramInfos = constructorInfos[i].GetParameters(); bool isPerfect; bool isObjectArrayArgTmp; if (IsMatchParameter(info.OperationTypeInfo != null, argTypes, paramInfos, out isPerfect, out isObjectArrayArgTmp)) { if (isPerfect) { constructorList.Clear(); constructorList.Add(constructorInfos[i]); break; } constructorList.Add(constructorInfos[i]); } if (isObjectArrayArgTmp) { isObjectArrayArg = true; } } //発見できなかった。 if (constructorList.Count == 0) { if (isObjectArrayArg) { throw new InformationException(string.Format(CultureInfo.CurrentCulture, ResourcesLocal.Instance.ErrorNotFoundConstractorFormatForObjectArray, type.Name, MakeErrorInvokeArgInfo(argTypes))); } else { throw new InformationException(string.Format(CultureInfo.CurrentCulture, ResourcesLocal.Instance.ErrorNotFoundConstractorFormat, type.Name, MakeErrorInvokeArgInfo(argTypes))); } } if (constructorList.Count != 1) { //オーバーロード解決に失敗 throw new InformationException(string.Format(CultureInfo.CurrentCulture, ResourcesLocal.Instance.ErrorManyFoundConstractorFormat, type.Name, MakeErrorInvokeArgInfo(argTypes))); } //インスタンス生成 object instance = constructorList[0].Invoke(args); //ref, outの解決 ReflectArgsAfterInvoke(varManager, info.Arguments, args); //変数登録 return(new ReturnInfo(varManager.Add(instance))); }