C# 为什么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(

在使用匿名托管的动态方法时,有人能解释一下为什么我在公共类上的公共虚拟方法中得到了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());
    }
}
公共类程序
{
公共虚拟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) { }
}