您可以加载一个令牌来获取RuntimeTypeHandle
然后调用Type.GetTypeFromHandle
.
在newobj <ctor>
通过与上述相同的安全异常进行处理之后。但是,我成功使用了Activator.CreateInstance
这是有效的 MSIL(请注意,首先进行类型检查(解决原始问题),然后是如何工作、创建和返回的示例private struct ListBuilder<T>
:
.method public static object IsRuntimeType(class [mscorlib]System.Type 'type') cil managed
{
// Code size 48 (0x30)
.maxstack 5
IL_0000: ldarg.0
IL_0001: ldtoken [mscorlib]System.RuntimeType
IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000b: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
class [mscorlib]System.Type)
IL_0010: pop
IL_0011: ldtoken valuetype [mscorlib]System.RuntimeType/ListBuilder`1<string>
IL_0016: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001b: ldc.i4.1
IL_001c: newarr [mscorlib]System.Object
IL_0021: dup
IL_0022: ldc.i4.0
IL_0023: ldc.i4.0
IL_0024: box [mscorlib]System.Int32
IL_0029: stelem.ref
IL_002a: call object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type,
object[])
IL_002f: ret
} // end of method Dyn::IsRuntimeType
这是用于创建动态 DLL 并测试上面的代码的 CSharp,上面的 MSIL 是使用 ILDASM.exe 从中提取的
var asmName = new AssemblyName("MsilDyn");
AppDomain domain = AppDomain.CurrentDomain;
AssemblyBuilder wrapperAssembly =
domain.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.RunAndSave);
var assemblyPath = asmName.Name + ".dll";
ModuleBuilder wrapperModule =
wrapperAssembly.DefineDynamicModule(asmName.Name,
assemblyPath);
// Define a type to contain the method.
TypeBuilder typeBuilder =
wrapperModule.DefineType("Dyn", TypeAttributes.Public);
MethodAttributes atts = MethodAttributes.Public | MethodAttributes.Static;
MethodBuilder methodBuilder =
typeBuilder.DefineMethod($"IsRuntimeType",
atts,
typeof(object),
new[] { typeof(Type) });
methodBuilder.DefineParameter(1, ParameterAttributes.None, "type");
ILGenerator il = methodBuilder.GetILGenerator();
var assem = typeof(string).Assembly;
var t = assem.GetType("System.RuntimeType");
var nestedList = t.GetMembers();
var resolveType = typeof(Type).GetMethod("GetType", new[] { typeof(string) });//., BindingFlags.Static | BindingFlags.Public);
var opEqual = typeof(Type).GetMethod("op_Equality");
var getTypeHandle = typeof(Type).GetMethod("GetTypeFromHandle");
var runtimeType = Type.GetType("System.RuntimeType");
var listBuilderType = (TypeInfo)runtimeType.GetMember("ListBuilder`1",
BindingFlags.Public | BindingFlags.NonPublic)[0];
var ListBuilderOfStringType = listBuilderType.MakeGenericType(new[] { typeof(string) });
// From C#
/*
var ctor = listBuilderType.GetConstructor(new[] { typeof(int) });
var instance = Activator.CreateInstance(ListBuilderOfStringType, new object[] { 0 });
*/
var listBuilderCtorArgs = new[] { typeof(Type), typeof(object[]) };
var ctor = typeof(Activator).GetMethod("CreateInstance", listBuilderCtorArgs);
// Generate an MSIL example of working with the RuntimeType for comparison
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldtoken, runtimeType);
il.Emit(OpCodes.Call, getTypeHandle);
il.Emit(OpCodes.Call, opEqual);
il.Emit(OpCodes.Pop);
// Generate an MSIL of creating RuntimeType.ListBuilder<string>
il.Emit(OpCodes.Ldtoken, ListBuilderOfStringType);
il.Emit(OpCodes.Call, getTypeHandle);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Box, typeof(int));
il.Emit(OpCodes.Stelem_Ref);
il.Emit(OpCodes.Call, ctor);
il.Emit(OpCodes.Ret);
var result = typeBuilder.CreateType();
wrapperAssembly.Save(assemblyPath);
var method = result.GetMethod("IsRuntimeType", BindingFlags.Public | BindingFlags.Static);
var stringType = typeof(string);
var listBuilderOfStringInstance = method.Invoke(null, new[] { stringType });