Пример #1
0
        /// <summary>
        /// リクエストされた型でジェネリックなパラメータを持つジェネリック型の型を確定します。
        /// </summary>
        /// <param name="col"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private Type MakeRequestGenericType(MultiRootConnector col, Type type)
        {
            List <Type> argTypes = new List <Type>();

            foreach (var gat in type.GetGenericArguments())
            {
                if (gat.IsGenericType)
                {
                    // パラメータがジェネリックだった

                    var ngt = MakeRequestGenericType(col, gat);
                    argTypes.Add(ngt);
                }
                else if (gat.IsGenericParameter)
                {
                    argTypes.Add(GetRequestType(col, gat.Name));
                }
                else
                {
                    // ジェネリックでないパラメータはそのまま使う

                    argTypes.Add(gat);
                }
            }
            // 確定した型を返す(repType を使って MakeGenericType しては駄目)
            Type nType = CbST.GetTypeEx(type.Namespace + "." + type.Name);

            return(nType.MakeGenericType(argTypes.ToArray()));
        }
Пример #2
0
        private static ICbValue _StructValue(Type type, string name, Type openedType)
        {
            if (type is null)
            {
                return(null);
            }
            string typeName = type.FullName;

            if (type.IsByRef)
            {
                // リファレンス(スクリプト変数接続)

                typeName = typeName.Replace("&", "");
                type     = CbST.GetTypeEx(typeName);
            }
            if (type.IsByRefLike)
            {
                // ref-like型構造体は、ジェネリック型引数にできない

                return(null);
            }

            Type cbStructType = openedType.MakeGenericType(type);

            object result = cbStructType.InvokeMember(
                nameof(CbStruct <dummy> .Create),      //"Create",
                BindingFlags.InvokeMethod,
                null, null, new object[] { name }) as ICbValue;

            return(result as ICbValue);
        }
Пример #3
0
        /// <summary>
        /// オリジナル型情報から CbClass<type>型の変数を返します。
        /// </summary>
        /// <param name="type">オリジナルのクラスの型</param>
        /// <param name="name"></param>
        /// <returns>CbClass<T>型の変数</returns>
        public static ICbValue ClassValue(Type type, string name)
        {
            if (type is null)
            {
                return(null);
            }

            string typeName = type.FullName;

            if (typeName is null)
            {
                typeName = type.Name;
            }
            if (type.IsByRef)
            {
                // リファレンス(スクリプト変数接続)

                typeName = typeName.Replace("&", "");
                type     = CbST.GetTypeEx(typeName);
                if (type is null)
                {
                    return(null);
                }
            }
            if (type.IsByRefLike)
            {
                // ref-like型構造体は、ジェネリック型引数にできない

                return(null);
            }
            if (!type.IsVisible && !type.IsTypeDefinition)
            {
                // 理由はわからないがこの条件は MakeGenericType が通らない

                return(null);
            }
            if (type.IsPointer)
            {
                // ポインタ型は、対象外

                return(null);
            }
            if (type.IsValueType)
            {
                // 未知の値型(今の所、対応する予定は無い)
                // IntPtr 型など

                return(null);
            }

            Type openedType  = typeof(CbClass <>); //CapybaraVS.Script.CbClass`1
            Type cbClassType = openedType.MakeGenericType(type);

            object result = cbClassType.InvokeMember(
                nameof(CbClass <CbInt> .Create),      //"Create",
                BindingFlags.InvokeMethod,
                null, null, new object[] { name }) as ICbValue;

            return(result as ICbValue);
        }
Пример #4
0
        public static ICbValue _EnumValue(Type type, string name, Type openedType)
        {
            if (type is null)
            {
                return(null);
            }
            string typeName = type.FullName;

            if (type.IsByRef)
            {
                // リファレンス(スクリプト変数接続)

                typeName = typeName.Replace("&", "");
                type     = CbST.GetTypeEx(typeName);
            }
            if (type.IsByRefLike)
            {
                // ref-like型構造体は、ジェネリック型引数にできない(不要だろうけど…)

                return(null);
            }
            Type cbEnumType = openedType.MakeGenericType(type);

            if (CbST.GetTypeEx(type) is null)
            {
                return(null);
            }

            object result = cbEnumType.InvokeMember("Create", BindingFlags.InvokeMethod,
                                                    null, null, new object[] { name }) as ICbValue;

            return(result as ICbValue);
        }
Пример #5
0
        public CbEnum(string name = "")
        {
            Type type = CbST.GetTypeEx(typeof(T));

            Value = Enum.Parse(type, Enum.GetNames(type)[0]) as Enum;
            Name  = name;
        }
Пример #6
0
 /// <summary>
 /// CbEnum<T> 型なら同様の型の変数を返します。
 /// </summary>
 /// <param name="value">参考変数</param>
 /// <param name="name">変数名</param>
 /// <returns>CbEnum<T>型の変数</returns>
 public static ICbValue EnumValue(ICbValue value, string name)
 {
     if (value is ICbEnum cbEnum)
     {
         return(EnumValue(CbST.GetTypeEx(cbEnum.ItemName), name));
     }
     return(null);
 }
Пример #7
0
        /// <summary>
        /// 構造体を判定します。
        /// </summary>
        /// <param name="type">true==構造体</param>
        /// <returns></returns>
        public static bool IsStruct(System.Type type)
        {
            if (type is null)
            {
                return(false);
            }
            if (type.IsByRef)
            {
                // リファレンスの場合は、リファレンスで無い場合の型情報を評価する(スクリプトの仕組み上の条件)

                string name = type.FullName;
                if (name is null)
                {
                    name = type.Name;
                }

                return(IsStruct(CbST.GetTypeEx(name.Replace("&", ""))));
            }
            return(type.IsValueType && !type.IsPrimitive && !type.IsEnum);
        }
Пример #8
0
        /// <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;
            }
        }
Пример #9
0
        /// <summary>
        /// メソッド呼び出し処理を実装する
        /// </summary>
        /// <param name="col">スクリプトのルートノード</param>
        /// <param name="dummyArgumentsControl">仮引数管理</param>
        protected bool ImplAsset(
            MultiRootConnector col,
            DummyArgumentsControl dummyArgumentsControl,
            string exTitle)
        {
            Type            classType  = ClassType;
            string          funcTitle  = FuncTitle;
            Func <ICbValue> returnType = ReturnType;

            if (classType.IsGenericType)
            {
                // ジェネリッククラスの型を確定する

                var data = ReturnType().Data;
                if (data is CbGeneMethArg gmaType)
                {
                    List <Type> argTypes = new List <Type>();
                    for (int i = 0; i < typeRequests.Count; ++i)
                    {
                        argTypes.Add(col.SelectedVariableType[i]);
                    }

                    //クラスの型を確定した型で差し替える
                    classType = classType.MakeGenericType(argTypes.ToArray());

                    if (IsConstructor)
                    {
                        returnType = CbST.CbCreateTF(classType);
                        if (funcTitle.Contains("<"))
                        {
                            // 確定した型情報に差し替える

                            funcTitle = funcTitle.Substring(0, funcTitle.IndexOf("<"));
                        }
                    }
                }
                else if (CbSTUtils.HaveGenericParamater(classType))
                {
                    // ユーザー選択ではなく直接 self からコピーされた型の場合は、そのまま内容を登録する

                    List <Type> argTypes = new List <Type>();
                    for (int i = 0; i < typeRequests.Count; ++i)
                    {
                        argTypes.Add(col.SelectedVariableType[i]);
                    }

                    //クラスの型を確定した型で差し替える
                    classType = CbST.GetTypeEx(classType.FullName).MakeGenericType(argTypes.ToArray());
                }
            }

            {// 返し値の型を差し替える
                var methodReturnType = returnType();
                if (methodReturnType.MyType == typeof(CbClass <CbGeneMethArg>))
                {
                    // 未確定なジェネリック型を確定した型で差し替える

                    // 引数の型を差し替える
                    Type repType = GetConfirmedType(col, (CbGeneMethArg)methodReturnType.Data);
                    returnType = CbST.CbCreateTF(repType);
                }
            }

            List <ICbValue> argumentTypeList = new List <ICbValue>();

            if (ArgumentTypeList != null)
            {
                // 引数用の変数を用意する

                foreach (var node in ArgumentTypeList)
                {
                    var argumentType = node.CreateArgument();
                    if (argumentType.MyType == typeof(CbClass <CbGeneMethArg>))
                    {
                        // 未確定なジェネリック型を確定した型で差し替える

                        // 引数の型を差し替える
                        Type replaceArgumentType = GetConfirmedType(col, (CbGeneMethArg)argumentType.Data);
                        argumentType = CbST.CbCreate(replaceArgumentType, argumentType.Name);
                    }
                    argumentTypeList.Add(argumentType);
                }
            }

            col.OldSpecification = oldSpecification;
            col.MakeFunction(
                funcTitle + exTitle,
                NodeHelpText,
                returnType,
                argumentTypeList,
                new Func <List <ICbValue>, DummyArgumentsStack, ICbValue>(
                    (arguments, cagt) =>
            {
                var ret = returnType();
                if (dummyArgumentsControl != null && dummyArgumentsControl.IsInvalid(cagt))
                {
                    return(ret);        // 実行環境が有効でない
                }
                ImplCallMethod(col, classType, dummyArgumentsControl, arguments, cagt, ret);
                return(ret);
            }
                    )
                );

            argumentTypeList.Clear();

            return(true);
        }
Пример #10
0
        static public string __GetTypeName(Type type)
        {
            if (type == typeof(Nullable))
            {
                return(type.Name);
            }

            bool isGeneName    = false;
            bool isNotGeneName = false;

            if (type.IsGenericType)
            {
                // ジェネリック型内のジェネリックCbクラス用

                if (type.GetGenericTypeDefinition() == typeof(CbClass <>) ||
                    type.GetGenericTypeDefinition() == typeof(CbStruct <>) ||
                    type.GetGenericTypeDefinition() == typeof(CbEnum <>))
                {
                    isNotGeneName = true;
                }
                isGeneName = true;
            }
            else if (type.Name.Contains("`"))
            {
                // out 修飾されていた場合あり得る

                isGeneName = true;
            }

            string typeName = type.FullName;

            if (typeName is null)
            {
                typeName = type.Name;
            }

            if (type.IsByRef)
            {
                // リファレンスは一先ず外す

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

            string geneString = "";

            if (type.IsArray)
            {
                // 配列は一先ず外す

                typeName = typeName.Replace("[]", "");
            }

            try
            {
                CbTypeNameListRwLock.AcquireReaderLock(Timeout.Infinite);
                if (CbTypeNameList.ContainsKey(typeName))
                {
                    return(CbTypeNameList[typeName]);
                }
            }
            finally
            {
                CbTypeNameListRwLock.ReleaseReaderLock();
            }

            if (isGeneName)
            {
                if (typeName.Contains("`"))
                {
                    // ジェネリック引数文字以降を削除

                    typeName = typeName.Substring(0, typeName.IndexOf("`"));
                }

                foreach (Type arg in type.GenericTypeArguments)
                {
                    string newName = _GetTypeName(arg);
                    if (geneString.Length != 0)
                    {
                        geneString += ",";
                    }
                    geneString += newName;
                }
                if (!isNotGeneName)
                {
                    if (geneString == "")
                    {
                        string cname = type.FullName;
                        if (cname is null)
                        {
                            // どうにもならない?

                            return("*Unsupported type*");
                        }
                        if (cname != null && cname.StartsWith("System.ArraySegment`"))
                        {
                            // ArraySegment は、強引に対応

                            if (type.IsGenericType)
                            {
                                return(GetGenericTypeName(type));
                            }

                            cname = cname.Substring(cname.IndexOf('['));
                            cname = cname.Substring(0, cname.IndexOf(','));
                            cname = cname.Replace("[", "");
                            return($"ArraySegment<{__GetTypeName(CbST.GetTypeEx(cname))}>");
                        }
                        else
                        {
                            if (cname.Last() == '&')
                            {
                                // リファレンスを取った型で試してみる

                                cname = cname.TrimEnd('&');
                                return(__GetTypeName(CbST.GetTypeEx(cname)));
                            }
                            else if (cname.EndsWith("[]"))
                            {
                                // 配列を取った型で試してみる

                                cname = cname.TrimEnd(']');
                                cname = cname.TrimEnd('[');
                                return(__GetTypeName(CbST.GetTypeEx(cname)));
                            }
                            else if (type.ContainsGenericParameters)
                            {
                                // ジェネリックなパラメータを持っている

                                return(GetGenericTypeName(type));
                            }
                            else
                            {
                                Debug.Assert(false);
                            }
                        }
                    }
                    else
                    {
                        geneString = "<" + geneString + ">";
                    }
                }
            }

            // ネームスペースを省略できるかチェックをここで行い、省略できるなら省略する
            typeName = Optimisation(typeName);

            try
            {
                CbTypeNameListRwLock.AcquireReaderLock(Timeout.Infinite);
                if (CbTypeNameList.ContainsKey(typeName))
                {
                    typeName = CbTypeNameList[typeName];
                }
            }
            finally
            {
                CbTypeNameListRwLock.ReleaseReaderLock();
            }

            if (type.IsEnum || type.IsInterface || type.IsClass)
            {
                // enum定義のネームスペースを削除

                typeName = typeName.Substring(typeName.IndexOf("+") + 1, typeName.Length - typeName.IndexOf("+") - 1);
            }

            if (isNotGeneName)
            {
                return(Optimisation(geneString));
            }

            if (typeName == "Nullable")
            {
                typeName   = geneString.Substring(1).Split('>')[0] + "?";
                geneString = "";
            }

            return(Optimisation(typeName + geneString));
        }
Пример #11
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);
        }