익명으로 호스팅 된 동적 메서드를 사용할 때 설명 할 수있는 사람이 공개 클래스의 공개 가상 메서드에 대해 ldvirtftn에 의해 확인할 수없는 예외가 발생하는 이유는 무엇입니까? 메소드가 소유 한 경우, 예외를 throw하지 않습니다Ldvirtftn을 확인할 수없는 이유는 무엇입니까?
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());
}
}
:
여기[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>()
.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는 type 매개 변수를 사용하여 동적 메서드의 서명을 결정하기 만합니다. 방법은 다음과 같습니다 ::
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이 검증의 가설이 아닌 가능합니다. –
사실, 그렇다면이 메소드에 소유 유형을 지정하면 검증 문제가 사라지게되는 이유는 무엇입니까? –