我试图调用以下MSIL方法:
.method public hidebysig static bool IsRuntimeType(class [mscorlib]System.Type 'type') cil managed {
.maxstack 2
ldarg.0
isinst [mscorlib]System.RuntimeType
ldnull
cgt.un
ret
} // end of method Program::IsRuntimeType
但是,尝试执行该行时会发生此异常:
isinst [mscorlib]System.RuntimeType
是的,我知道JIT验证,但是我已经尝试了很多东西而且他们没有工作,或者我只是做错了,我不确定。另外,我对这个主题找不到多少。
我尝试了以下(将它们中的一些组合在一起):
[SecurityPermissionAttribute(SecurityAction.Demand, SkipVerification = true)]
属性(同时使用SecurityAction.Assert
)new ReflectionPermission(ReflectionPermissionFlag.MemberAccess | ReflectionPermissionFlag.RestrictedMemberAccess).Demand();
(以及.Assert()
)new SecurityPermission(SecurityPermissionFlag.AllFlags).Demand();
(以及.Assert()
)这些要求和断言都没有抛出异常。
澄清一下,这只是一个例子。主要思想是使代码工作并绕过JIT的验证。这种特殊的方法无法在没有反射的C#中完成,我想避免它,因为它非常昂贵,但这不是重点。
有没有什么方法可以让我的代码执行而JIT不会抛出TypeAccessException
(比如当你调用一个动态方法时,你将true
传递给skipVerification
参数&# 39; s构造函数)?
答案 0 :(得分:0)
无论是否启用验证,即使直接使用CIL,也不能违反类型辅助功能或成员可见性。这是CIL代码的正确性问题,而不仅仅是类型安全性。这是检查给定类型对象是否为RuntimeType
的实例的正确方法。
static bool IsTypeRuntimeType(Type type)
{
return typeof(object).GetType() == type.GetType();
}
答案 1 :(得分:0)
您可以加载令牌以获取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
这是CSharp,用于创建动态DLL和测试上面的代码,使用ILDASM.exe从上面提取MSIL
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 });