C# 为什么Ldvirtftn无法验证?
在使用匿名托管的动态方法时,有人能解释一下为什么我在公共类上的公共虚拟方法中得到了ldvirtftn无法验证的异常吗?我还设置了以下程序集级属性:C# 为什么Ldvirtftn无法验证?,c#,reflection.emit,dynamicmethod,C#,Reflection.emit,Dynamicmethod,在使用匿名托管的动态方法时,有人能解释一下为什么我在公共类上的公共虚拟方法中得到了ldvirtftn无法验证的异常吗?我还设置了以下程序集级属性: [assembly: SecurityTransparent] [assembly: SecurityRules(SecurityRuleSet.Level2,SkipVerificationInFullTrust=true)] 下面是示例代码: public class Program { public virtual void Foo(
[assembly: SecurityTransparent]
[assembly: SecurityRules(SecurityRuleSet.Level2,SkipVerificationInFullTrust=true)]
下面是示例代码:
public class Program
{
public virtual void Foo() {}
public static void Main(string[] args)
{
Action<ILGenerator> genfunc = il => il
.newobj<Program>()
.ldvirtftn(typeof(Program).GetMethod("Foo"))
.ret();
try
{
Console.WriteLine(CodeGen.CreateDelegate<Func<IntPtr>>(genfunc).Invoke());
}
catch (System.Security.VerificationException) { }
Console.WriteLine(CodeGen.CreateDelegate<Func<IntPtr>>(genfunc,owner:typeof(Program)).Invoke());
}
}
公共类程序
{
公共虚拟void Foo(){}
公共静态void Main(字符串[]args)
{
动作genfunc=il=>il
.newobj()
.ldvirtftn(typeof(Program).GetMethod(“Foo”))
.ret();
尝试
{
WriteLine(CodeGen.CreateDelegate(genfunc.Invoke());
}
catch(系统安全性验证异常){}
Console.WriteLine(CodeGen.CreateDelegate(genfunc,所有者:typeof(Program)).Invoke());
}
}
如果该方法是自有的,那么它不会引发异常
更奇怪的是,如果我像这样更改代码,那么这两个方法编译并运行时都不会出现问题:
public class Program
{
public virtual void Foo() {}
public static void Main(string[] args)
{
Action<ILGenerator> genfunc = il => il
.newobj<Program>()
.dup()
.ldvirtftn(typeof(Program).GetMethod("Foo"))
.newobj<Action>(typeof(object),typeof(IntPtr))
.ret();
try
{
Console.WriteLine(CodeGen.CreateDelegate<Func<Action>>(genfunc).Invoke());
}
catch (System.Security.VerificationException) { }
Console.WriteLine(CodeGen.CreateDelegate<Func<Action>>(genfunc,owner:typeof(Program)).Invoke());
}
}
公共类程序
{
公共虚拟void Foo(){}
公共静态void Main(字符串[]args)
{
动作genfunc=il=>il
.newobj()
.dup()
.ldvirtftn(typeof(Program).GetMethod(“Foo”))
.newobj(typeof(object),typeof(IntPtr))
.ret();
尝试
{
WriteLine(CodeGen.CreateDelegate(genfunc.Invoke());
}
catch(系统安全性验证异常){}
Console.WriteLine(CodeGen.CreateDelegate(genfunc,所有者:typeof(Program)).Invoke());
}
}
这段代码是用反射库编写的
CreateDelegate只是使用类型参数来确定动态方法的签名。方法如下:
public static TDelegate CreateDelegate<TDelegate>(
Action<ILGenerator> genfunc, string name = "", object target = null, Type owner = null, bool skipVisibility = false)
where TDelegate : class
{
var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
var parameters = invokeMethod.GetParameters();
var paramTypes = new Type[parameters.Length + 1];
paramTypes[0] = typeof(object);
parameters.Select(p => p.ParameterType).ToArray().CopyTo(paramTypes, 1);
var method = owner != null ?
new DynamicMethod(name, invokeMethod.ReturnType, paramTypes, owner, skipVisibility) :
new DynamicMethod(name, invokeMethod.ReturnType, paramTypes, skipVisibility);
genfunc(method.GetILGenerator());
return method.CreateDelegate(typeof(TDelegate), target) as TDelegate;
}
公共静态TDelegate CreateDelegate(
操作genfunc,字符串名称=”,对象目标=null,类型所有者=null,bool skipVisibility=false)
TDelegate:类在哪里
{
var invokeMethod=typeof(TDelegate).GetMethod(“Invoke”);
var parameters=invokeMethod.GetParameters();
var paramTypes=新类型[parameters.Length+1];
paramTypes[0]=typeof(对象);
parameters.Select(p=>p.ParameterType).ToArray().CopyTo(paramTypes,1);
var method=owner!=null?
新的DynamicMethod(名称、invokeMethod.ReturnType、paramTypes、所有者、skipVisibility):
新的DynamicMethod(名称、invokeMethod.ReturnType、paramTypes、skipVisibility);
genfunc(method.GetILGenerator());
返回方法.CreateDelegate(typeof(TDelegate),target)作为TDelegate;
}
ldvirtfn将本机int加载到堆栈中。我认为您需要先将其转换为IntPtr,然后再返回。ldvirtfn将本机int加载到堆栈中。我认为您需要先将其转换为IntPtr,然后再返回。奇怪的行为(IntPtr!=IntPtr):
//工作正常
公共静态无效F_Ldvirtftn_Action()
{
动作genfunc=il=>
{
Emit(opcode.Newobj,typeof(Program).GetConstructor(Type.EmptyTypes));
发射(操作码Dup);
Emit(opcode.Ldvirtftn,typeof(Program.GetMethod(“Foo2”));
Emit(opcode.Newobj,typeof(Action).GetConstructor(new[]{typeof(object),typeof(IntPtr)});
发射(操作码Ret);
};
WriteLine(CreateDelegate(genfunc.Invoke());
}
//失败:VerificationException:操作可能会使运行时不稳定
公共静态无效F_IntPtr_Action()
{
动作genfunc=il=>
{
Emit(opcode.Newobj,typeof(Program).GetConstructor(Type.EmptyTypes));
发射(操作码Dup);
il.Emit(opcode.Call,typeof(Program.GetMethod)(“Ptr”);
Emit(opcode.Newobj,typeof(Action).GetConstructor(new[]{typeof(object),typeof(IntPtr)});
发射(操作码Ret);
};
WriteLine(CreateDelegate(genfunc.Invoke());
}
//失败:VerificationException:操作可能会使运行时不稳定
公共静态无效F_Ldvirtftn_MyAction()
{
动作genfunc=il=>
{
Emit(opcode.Newobj,typeof(Program).GetConstructor(Type.EmptyTypes));
发射(操作码Dup);
Emit(opcode.Ldvirtftn,typeof(Program.GetMethod(“Foo2”));
Emit(OpCodes.Newobj,typeof(MyAction).GetConstructor(new[]{typeof(object),typeof(IntPtr)});
发射(操作码Ret);
};
WriteLine(CreateDelegate(genfunc.Invoke());
}
//正常工作
公共静态无效F_IntPtr_MyAction()
{
动作genfunc=il=>
{
Emit(opcode.Newobj,typeof(Program).GetConstructor(Type.EmptyTypes));
发射(操作码Dup);
il.Emit(opcode.Call,typeof(Program.GetMethod)(“Ptr”);
Emit(OpCodes.Newobj,typeof(MyAction).GetConstructor(new[]{typeof(object),typeof(IntPtr)});
发射(操作码Ret);
};
WriteLine(CreateDelegate(genfunc.Invoke());
}
公共静态IntPtr Ptr(对象z)
{
返回IntPtr.Zero;
}
公共集体诉讼
{
公共MyAction(对象z,IntPtr adr){}
}
奇怪的行为(IntPtr!=IntPtr):
//工作正常
公共静态无效F_Ldvirtftn_Action()
{
动作genfunc=il=>
{
Emit(opcode.Newobj,typeof(Program).GetConstructor(Type.EmptyTypes));
发射(操作码Dup);
Emit(opcode.Ldvirtftn,typeof(Program.GetMethod(“Foo2”));
Emit(opcode.Newobj,typeof(Action).GetConstructor(new[]{typeof(object),typeof(IntPtr)});
发射(操作码Ret);
};
WriteLine(CreateDelegate(genfunc.Invoke());
}
//失败:VerificationException:操作可能会使运行时不稳定
公共静态无效F_IntPtr_Action()
{
动作genfunc=il=>
{
Emit(opcode.Newobj,typeof(Program).GetConstructor(Type.EmptyTypes));
发射(操作码Dup);
il.Emit(opcode.Call,typeof(Program.GetMethod)(“Ptr”);
Emit(opcode.Newobj,typeof(Action).GetConstructor(new[]{typeof(object),typeof(IntPtr)});
发射(操作码Ret);
};
WriteLine(CreateDelegate(genfunc.Invoke());
}
//失败:VerificationException:操作可能会使运行时不稳定
//work normal
public static void F_Ldvirtftn_Action()
{
Action<ILGenerator> genfunc = il =>
{
il.Emit(OpCodes.Newobj, typeof(Program).GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldvirtftn, typeof(Program).GetMethod("Foo2"));
il.Emit(OpCodes.Newobj, typeof(Action).GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
il.Emit(OpCodes.Ret);
};
Console.WriteLine(CreateDelegate<Func<object>>(genfunc).Invoke());
}
// failed: VerificationException: Operation could destabilize the runtime
public static void F_IntPtr_Action()
{
Action<ILGenerator> genfunc = il =>
{
il.Emit(OpCodes.Newobj, typeof(Program).GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Call, typeof(Program).GetMethod("Ptr"));
il.Emit(OpCodes.Newobj, typeof(Action).GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
il.Emit(OpCodes.Ret);
};
Console.WriteLine(CreateDelegate<Func<object>>(genfunc).Invoke());
}
// failed: VerificationException: Operation could destabilize the runtime
public static void F_Ldvirtftn_MyAction()
{
Action<ILGenerator> genfunc = il =>
{
il.Emit(OpCodes.Newobj, typeof(Program).GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldvirtftn, typeof(Program).GetMethod("Foo2"));
il.Emit(OpCodes.Newobj, typeof(MyAction).GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
il.Emit(OpCodes.Ret);
};
Console.WriteLine(CreateDelegate<Func<object>>(genfunc).Invoke());
}
//work normal
public static void F_IntPtr_MyAction()
{
Action<ILGenerator> genfunc = il =>
{
il.Emit(OpCodes.Newobj, typeof(Program).GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Call, typeof(Program).GetMethod("Ptr"));
il.Emit(OpCodes.Newobj, typeof(MyAction).GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
il.Emit(OpCodes.Ret);
};
Console.WriteLine(CreateDelegate<Func<object>>(genfunc).Invoke());
}
public static IntPtr Ptr(object z)
{
return IntPtr.Zero;
}
public class MyAction
{
public MyAction(object z, IntPtr adr) { }
}