/// <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())); }
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); }
/// <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); }
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); }
public CbEnum(string name = "") { Type type = CbST.GetTypeEx(typeof(T)); Value = Enum.Parse(type, Enum.GetNames(type)[0]) as Enum; Name = name; }
/// <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); }
/// <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); }
/// <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> 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); }
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)); }
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); }