을 DynamicMethod를 만듭니다. 이 바이트에서 동적 메서드를 만들고 실행하려고합니다. 여기에 내가 뭘하려고 오전의 예 :내가 DynamicMethod와 놀아 다음을 수행하는 것을 목표로하고 작업에서 <T> 지침
class Program
{
static void Main(string[] args)
{
//Create action and execute
Action<string> myAction = s =>
{
Console.WriteLine("Hello " + s);
};
myAction("World");
//Get IL bytes
byte[] ilBytes = myAction.GetMethodInfo().GetMethodBody().GetILAsByteArray();
DynamicMethod dynamicCallback = new DynamicMethod("myAction", typeof(void), new Type[] { typeof(string) });
DynamicILInfo dynamicIlInfo = dynamicCallback.GetDynamicILInfo();
dynamicIlInfo.SetCode(ilBytes, 100);
dynamicCallback.Invoke(null, new object[] { "World" });
}
}
dynamicCallback.Invoke(null, new object[] { "World" })
우리 얻을 "던져 예외 :가 mscorlib.dll에서 'System.BadImageFormatException'를"호출.
내가 가장 잘 모르겠다는 점은 SetCode()
의 두 번째 인수로 사용해야하는 것이고, 'maxStackSize'로 사용해야하는 것은 무엇입니까? 초기 액션과 동일한 값을 설정하려면 어떻게해야합니까? 그러나 이것이 이것이 예외의 이유는 아니라고 생각합니다.
IL 바이트에서 동적 방법을 올바르게 만들려면 어떻게해야합니까?
솔루션 여기
내가 두디 켈 레티 (Keleti)가 제공하는 완벽한 솔루션을 요약하고 싶습니다 :
static void Main(string[] args)
{
Action<string> myAction = s =>
{
Console.WriteLine("Hello " + s);
};
MethodInfo method = myAction.GetMethodInfo();
object target = myAction.Target;
DynamicMethod dm = new DynamicMethod(
method.Name,
method.ReturnType,
new[] {method.DeclaringType}.
Concat(method.GetParameters().
Select(pi => pi.ParameterType)).ToArray(),
method.DeclaringType,
skipVisibility: true);
DynamicILInfo ilInfo = dm.GetDynamicILInfo();
var body = method.GetMethodBody();
SignatureHelper sig = SignatureHelper.GetLocalVarSigHelper();
foreach (LocalVariableInfo lvi in body.LocalVariables)
{
sig.AddArgument(lvi.LocalType, lvi.IsPinned);
}
ilInfo.SetLocalSignature(sig.GetSignature());
byte[] code = body.GetILAsByteArray();
ILReader reader = new ILReader(method);
DynamicMethodHelper.ILInfoGetTokenVisitor visitor = new DynamicMethodHelper.ILInfoGetTokenVisitor(ilInfo, code);
reader.Accept(visitor);
ilInfo.SetCode(code, body.MaxStackSize);
dm.Invoke(target, new object[] { target, "World" });
Console.ReadLine(); //Just to see the result
}
참고 : DynamicMethodHelper는 클래스 A blog post에 하이 보 루오에 의해 개발되고 설명되어 있지만, 또한 here에 직접 다운로드 할 수 있습니다.
리플렉션을 사용하여 maxStackSize 값을 가져올 수 없다고 생각합니다. 그러나 실제로, 그것은 여기의 문제가 아닙니다. 문제는'Console.WriteLine' 호출이 메타 데이터 토큰 (아마도 MethodRef)으로 인코딩되고 메타 데이터 토큰이 그것을 선언하는 모듈의 유효 범위에서만 유효하다는 것입니다. 'DynamicILInfo.GetTokenFor' 함수를 살펴보면, 다른 메타 데이터 항목과'DynamicMethod'에 유효한 유효 토큰을 가져옵니다. – thehennyy
@thehennyy 성공하지 않으려 고 시도했습니다. 편집을 참조하십시오. – Sjoerd222888
일리노이 바이트 배열의 오래된 토큰을'GetTokenFor' 메쏘드가 반환하는 새 토큰으로 대체해야합니다. – thehennyy