/// <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)));
        }