示例#1
0
        public virtual bool IsAssignment(ICbValue obj, bool isCast)
        {
            if (obj is ParamNameOnly)
            {
                return(false);
            }

            if (IsList)
            {
                ICbList cbList = GetListValue;

                if (isCast && cbList.IsArrayType && obj.IsList)
                {
                    return(true);    // ToArrya() を行う特殊なキャスト
                }
                if (isCast && obj.IsList)
                {
                    ICbList ListObj = obj.GetListValue;
                    if (ListObj.IsArrayType)
                    {
                        return(true);    // List<>(array) を行う特殊なキャスト
                    }
                }

                if (OriginalType.IsAssignableFrom(obj.OriginalType))
                {
                    return(true);
                }
            }
            return(CbSTUtils.IsAssignment(OriginalType, obj.OriginalType, isCast));
        }
        /// <summary>
        /// オリジナル型の値に変換します。
        /// </summary>
        /// <param name="value"></param>
        /// <param name="col"></param>
        /// <param name="dummyArgumentsControl"></param>
        /// <param name="dummyArgumentsStack"></param>
        /// <returns></returns>
        private object getBindObject(
            ICbValue value,
            MultiRootConnector col,
            DummyArgumentsControl dummyArgumentsControl,
            DummyArgumentsStack dummyArgumentsStack
            )
        {
            if (value.IsList)
            {
                ICbList cbList = value.GetListValue;

                // リストは、オリジナルの型のインスタンスを用意する

                if (dummyArgumentsControl is null)
                {
                    return(cbList.ConvertOriginalTypeList(col, dummyArgumentsStack));
                }
                else
                {
                    return(cbList.ConvertOriginalTypeList(dummyArgumentsControl, dummyArgumentsStack));
                }
            }
            else if (dummyArgumentsControl != null && value is ICbEvent cbEvent)
            {
                // Func<> 及び Action<> は、オリジナルの型のインスタンスを用意する

                if (cbEvent.Callback is null)
                {
                    return(null);
                }
                else
                {
                    Debug.Assert(dummyArgumentsControl != null);
                    return(cbEvent.GetCallbackOriginalType(dummyArgumentsControl, dummyArgumentsStack));
                }
            }
            if (value.IsNull)
            {
                return(null);
            }
            return(value.Data);
        }
        /// <summary>
        /// 返り値を処理します。
        /// </summary>
        /// <param name="col">スクリプトのルートノード</param>
        /// <param name="returnValue">返り値を格納する変数</param>
        /// <param name="result">メソッド呼び出しの返り値</param>
        private static void ProcReturnValue(MultiRootConnector col, ICbValue returnValue, object result)
        {
            if (returnValue.IsList)
            {
                ICbList retCbList = returnValue.GetListValue;
                retCbList.CopyFrom(result);
                col.LinkConnectorControl.UpdateValueData();
            }
            else if (result != null && returnValue is ICbEvent cbEvent)
            {
                // デリゲート型の返し値

                Type resultType = CbSTUtils.GetDelegateReturnType(result.GetType());

                if (!CbSTUtils.IsVoid(resultType))
                {
                    // 返し値のあるデリゲート型

                    cbEvent.Callback = (cagt) =>
                    {
                        ICbValue retTypeValue = null;
                        try
                        {
                            // イベントからの返り値を取得
                            object tempReturnValue = ((dynamic)result).Invoke(cagt.GetValue().Data);

                            // 直接メソッドを呼ぶため帰ってくるのは通常の値なので Cb タイプに変換する
                            retTypeValue      = CbST.CbCreate(tempReturnValue.GetType());
                            retTypeValue.Data = tempReturnValue;
                        }
                        catch (Exception ex)
                        {
                            col.ExceptionFunc(null, ex);
                        }
                        return(retTypeValue);
                    };
                }
                else
                {
                    // 返し値の無いデリゲート型

                    cbEvent.Callback = (cagt) =>
                    {
                        try
                        {
                            var argType = cagt.GetValue();
                            if (argType is null)
                            {
                                ((dynamic)result).Invoke(null);
                            }
                            else
                            {
                                ((dynamic)result).Invoke(argType.Data);
                            }
                        }
                        catch (Exception ex)
                        {
                            col.ExceptionFunc(null, ex);
                        }
                        return(new CbVoid());
                    };
                }
            }
            else
            {
                returnValue.Data = result;
            }
        }
        /// <summary>
        /// メソッド呼び出しの実装です。
        /// </summary>
        /// <param name="col">スクリプトのルートノード</param>
        /// <param name="dummyArgumentsControl">仮引数管理オブジェクト</param>
        /// <param name="callArguments">引数リスト</param>
        /// <param name="dummyArgumentsStack">仮引数スタック</param>
        /// <param name="returnValue">返り値</param>
        private void ImplCallMethod(
            MultiRootConnector col,
            Type classType,
            DummyArgumentsControl dummyArgumentsControl,
            List <ICbValue> callArguments,
            DummyArgumentsStack dummyArgumentsStack,
            ICbValue returnValue
            )
        {
            try
            {
                bool          isClassInstanceMethod = ArgumentTypeList != null && ArgumentTypeList[0].IsSelf && !IsConstructor;
                List <object> methodArguments       = null;

                methodArguments = SetArguments(
                    col,
                    dummyArgumentsControl,
                    callArguments,
                    dummyArgumentsStack,
                    isClassInstanceMethod,
                    methodArguments
                    );

                object classInstance = null;
                if (isClassInstanceMethod)
                {
                    // クラスメソッドの第一引数は、self(this)を受け取るのでクラスインスタンスとして扱う

                    classInstance = getBindObject(callArguments[0], col, dummyArgumentsControl, dummyArgumentsStack);
                    if (classInstance is null)
                    {
                        throw new Exception($"self(this) is invalid.");
                    }
                    // 返却方法が入っていないならセットしておく
                    var cbVSValue = callArguments[0];
                    if (!cbVSValue.IsDelegate && !cbVSValue.IsLiteral && cbVSValue.ReturnAction is null)
                    {
                        if (cbVSValue.IsList)
                        {
                            ICbList cbList = cbVSValue.GetListValue;
                            cbVSValue.ReturnAction = (value) =>
                            {
                                cbList.CopyFrom(value);
                            };
                        }
                        else if (!(cbVSValue is ICbClass))
                        {
                            cbVSValue.ReturnAction = (value) =>
                            {
                                cbVSValue.Data = value;
                            };
                        }
                    }
                }

                object result = CallMethod(
                    classInstance,
                    col,
                    classType,
                    callArguments,
                    isClassInstanceMethod,
                    methodArguments);

                ProcReturnValue(col, returnValue, result);
            }
            catch (Exception ex)
            {
                col.ExceptionFunc(returnValue, ex);
            }
        }
示例#5
0
        private static ICbValue _CbCreate(Type type, string name, bool isCancelClass)
        {
            string typeName = type.Name;

            if (!isCancelClass && type.IsByRef)
            {
                // リファレンス情報を消す

                typeName = typeName.Replace("&", "");
            }

            switch (typeName)
            {
            case nameof(Byte): return(CbByte.Create(name));

            case nameof(SByte): return(CbSByte.Create(name));

            case nameof(Int16): return(CbShort.Create(name));

            case nameof(Int32): return(CbInt.Create(name));

            case nameof(Int64): return(CbLong.Create(name));

            case nameof(UInt16): return(CbUShort.Create(name));

            case nameof(UInt32): return(CbUInt.Create(name));

            case nameof(UInt64): return(CbULong.Create(name));

            case nameof(Char): return(CbChar.Create(name));

            case nameof(Single): return(CbFloat.Create(name));

            case nameof(Double): return(CbDouble.Create(name));

            case nameof(Decimal): return(CbDecimal.Create(name));

            case nameof(Boolean): return(CbBool.Create(name));

            case nameof(String): return(CbString.Create(name));

            case nameof(Object): return(CbObject.Create(name));

            case nameof(CbText): return(CbText.Create(name));

            case nameof(CbImagePath): return(CbImagePath.Create(name));

            default:
                break;
            }

            if (type.IsArray)
            {
                // 配列は、List<>に置き換える

                string _mame = "xxx";
                if (type.FullName != null)
                {
                    _mame = type.FullName;
                }
                else if (type.Name != null)
                {
                    _mame = type.Name;
                }
                Type tType = CbST.GetTypeEx(_mame);
                if (tType != null)
                {
                    Type element = tType.GetElementType();
                    if (element != null)
                    {
                        Type collectionType = typeof(List <>).MakeGenericType(element);
                        var  ret            = CbList.Create(collectionType, name);
                        if (ret.IsList)
                        {
                            ICbList cbList = ret.GetListValue;
                            cbList.IsArrayType = true;
                        }
                        return(ret);
                    }
                }
                if (type.ContainsGenericParameters)
                {
                    return(CbGeneMethArg.NTF(name, type, type.GetGenericArguments(), false));
                }
            }

            if (type.IsEnum)
            {
                // 列挙型

                return(CbEnumTools.EnumValue(type, name));
            }

            if (!type.IsGenericType && CbSTUtils.IsDelegate(type))
            {
                // デリゲート型

                return(CbFunc.FuncValue(type, typeof(CbVoid), name));
            }

            if (CbSTUtils.HaveGenericParamater(type))
            {
                // 確定していない型なので仮の型に差し替える

                if (!type.IsPublic)
                {
                    return(null);
                }

                if (CbSTUtils.IsDelegate(type))
                {
                    // 確定していないデリゲート型

                    return(CbGeneMethArg.NTF(name, type, type.GetGenericArguments(), true));
                }
                return(CbGeneMethArg.NTF(name, type, type.GetGenericArguments(), false));
            }

            if (type.IsGenericType)
            {
                // ジェネリック型

                if (CbList.HaveInterface(type, typeof(IEnumerable <>)))
                {
                    // リスト管理(UIで特別扱い)

                    if (type.GenericTypeArguments.Length > 1)
                    {
                        return(null);
                    }

                    return(CbList.Create(type, name));
                }

                if (CbSTUtils.IsDelegate(type))
                {
                    // デリゲート型

                    var returnType = CbSTUtils.GetDelegateReturnType(type);
                    if (CbSTUtils.IsVoid(returnType))
                    {
                        return(CbFunc.FuncValue(type, typeof(CbVoid), name));
                    }
                    else
                    {
                        return(CbFunc.FuncValue(type, returnType, name));
                    }
                }

                if (type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    // Null許容型

                    if (type.GenericTypeArguments.Length > 1)
                    {
                        return(null);
                    }

                    Type param = type.GenericTypeArguments[0];
                    switch (param.Name)
                    {
                    case nameof(Byte): return(CbNullableByte.Create(name));

                    case nameof(SByte): return(CbNullableSByte.Create(name));

                    case nameof(Int16): return(CbNullableShort.Create(name));

                    case nameof(Int32): return(CbNullableInt.Create(name));

                    case nameof(Int64): return(CbNullableLong.Create(name));

                    case nameof(UInt16): return(CbNullableUShort.Create(name));

                    case nameof(UInt32): return(CbNullableUInt.Create(name));

                    case nameof(UInt64): return(CbNullableULong.Create(name));

                    case nameof(Char): return(CbNullableChar.Create(name));

                    case nameof(Single): return(CbNullableFloat.Create(name));

                    case nameof(Double): return(CbNullableDouble.Create(name));

                    case nameof(Decimal): return(CbNullableDecimal.Create(name));

                    case nameof(Boolean): return(CbNullableBool.Create(name));

                    default:
                        break;
                    }
                    if (CbStruct.IsStruct(param))
                    {
                        // 構造体

                        return(CbStruct.NullableStructValue(param, name));
                    }
                    if (param.IsEnum)
                    {
                        // 列挙型

                        return(CbEnumTools.NullableEnumValue(param, name));
                    }
                    Debug.Assert(false);
                    return(null);
                }

                // その他のジェネリックは、構造体かクラスとして扱う
                if (CbStruct.IsStruct(type))
                {
                    return(CbStruct.StructValue(type, name));
                }
                return(CbClass.ClassValue(type, name));
            }

            if (CbStruct.IsStruct(type))
            {
                // 構造体

                if (type.FullName == "System.Void")
                {
                    Debug.Assert(false);
                    return(null);
                }

                if (!isCancelClass)
                {
                    var ret = CbStruct.StructValue(type, name);
                    if (ret != null && ret is ICbStruct cbStruct)
                    {
                        return(_CbCreate(cbStruct.OriginalReturnType, name, true));
                    }
                }
                return(CbStruct.StructValue(type, name));
            }

            if (type.IsClass || type.IsInterface)
            {
                // クラス

                var elements = CbSTUtils.GetGenericIEnumerables(type);
                if (elements.Count() != 0)
                {
                    // IEnumerable<> を持っているのでリストとして扱う(ただし、オリジナルのデータ形式も保存する)

                    var elementType = elements.First();   // 最初に見つかった要素のみを対象とする(妥協)
                    var chgType     = CbList.Create(typeof(IEnumerable <>).MakeGenericType(new Type[] { elementType }), name);
                    (chgType as ICbList).CastType = type; // 元の型にキャスト(メソッドを呼ぶときは、オリジナルのデータ形式を参照する)
                    return(chgType);
                }

                if (!isCancelClass)
                {
                    var ret = CbClass.ClassValue(type, name);
                    if (ret != null && ret is ICbClass cbClass)
                    {
                        return(_CbCreate(cbClass.OriginalReturnType, name, true));
                    }
                }
                return(CbClass.ClassValue(type, name));
            }

            return(null);
        }