任何人都可以解釋何時使用匿名託管的動態方法爲什麼我得到一個公共類的公共虛擬方法ldvirtftn無法驗證的異常?我設置以下組件級別的屬性,以及:爲什麼Ldvirtftn無法驗證?
[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());
}
}
如果方法擁有,那麼它不會拋出異常。
更好奇的是,如果我改變的代碼,像這樣那麼這兩種方法編譯並沒有問題,運行:
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());
}
}
此代碼與反射庫寫入。
CodeGen.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;
}
MSIL不只是託管代碼。您也可以將原始的本機C++代碼編譯爲IL。由C++/CLI編譯器完成。 Opcodes.Ldvirtfn是重要的代碼類型,它從v表中挖掘函數指針。當抖動驗證器被擊中時,原始地址IntPtr,而不是驗證的可能性。 – 2012-03-31 22:04:20
的確如此,但爲什麼給該方法一個擁有類型會使驗證問題消失? – 2012-03-31 22:36:48