你可以这样做:
byte[] code = body.GetILAsByteArray();
ILReader reader = new ILReader(method);
ILInfoGetTokenVisitor visitor = new ILInfoGetTokenVisitor(ilInfo, code);
reader.Accept(visitor);
ilInfo.SetCode(code, body.MaxStackSize);
ILReader
是一门为你做艰苦工作的课程。您可以从以下位置复制它here https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/01/00/37/88/ILReader.zip.
Example:
MethodInfo method = ...
DynamicMethod dm = new DynamicMethod(
method.Name,
method.ReturnType,
method.GetParameters.Select(pi => pi.ParameterType).ToArray(),
method.DeclaringType,
skipVisibility: true\fasle - depends of your need);
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);
ILInfoGetTokenVisitor visitor = new ILInfoGetTokenVisitor(ilInfo, code);
reader.Accept(visitor);
ilInfo.SetCode(code, body.MaxStackSize);
如果您的方法是一个简单方法(不是通用的并且没有异常句柄),则 thid 应该可以工作。
如果您的方法是通用方法,则需要执行以下操作以将所有者类型传递给 DynamicMethod 构造函数:
var owner = method.DeclaringType.MakeGenericType(
method.DeclaringType.GetGenericArguments());
还有一件事,如果它仍然不起作用,并且您的方法是实例方法,请将方法的实例类型传递到参数数组的第一个单元格中DynamicMethod
构造函数。
Update
你无法通过null
here dm.Invoke(**null**, new object[] { "World" });
因为myAction
不是静态方法。
myAction
(Action<string>
) 实际上是新生成的类中保存该方法的方法。
但我检查了一下,即使我通过了,异常也会抛出myAction.Target
或该类型的新实例。异常(CLR 检测到无效程序)告诉您 IL 不完全正确。我现在无法确切地告诉您问题出在哪里,但如果这对您很重要,我可以在下周回去工作时检查一下。
无论如何,如果您只想查看 DynamicIlInfo.SetCode 的实际效果,您可以按原样使用代码,但只需更改方法信息即可:
class Program
{
static void Main(string[] args)
{
Action<string> myAction = s =>
{
Console.WriteLine("Hello " + s);
};
MethodInfo method = myAction.GetMethodInfo();
//Rest of your code
}
}
to this:
class Program
{
static void M(string s)
{
Console.WriteLine("Hello " + s);
}
static void Main(string[] args)
{
MethodInfo method = typeof (Program).GetMethod("M", BindingFlags.Static | BindingFlags.NonPublic);
//Rest of your code
}
}
更新2:
显然我昨天很累,我没有意识到你的错误。
正如我在原来的答案中所写的,
还有一件事,如果它仍然不起作用,并且您的方法是实例方法,请将方法的实例类型传递到参数数组的第一个单元格中DynamicMethod
构造函数。
所以你需要这样做:
DynamicMethod dm = new DynamicMethod(
method.Name,
method.ReturnType,
new[] {method.DeclaringType}.
Concat(method.GetParameters().
Select(pi => pi.ParameterType)).ToArray(),
method.DeclaringType,
skipVisibility: true);
并像这样调用动态方法:
dm.Invoke(myAction.Target, new object[] { myAction.Target, "World" });
现在工作完美了。