【发布时间】:2016-12-09 17:15:55
【问题描述】:
我想将一个方法从一个类转换为一个 IL 代码,然后通过调用它来执行它。我下面的例子来自 msdn:https://msdn.microsoft.com/en-us/library/system.reflection.emit.methodbuilder.createmethodbody(v=vs.110).aspx.
它准确地显示了我的需要,我的问题是从类方法生成 ILcode。
所以基本上我需要填写以下内容
byte[] ILcodes = new byte[] {
0x02, /* 02h is the opcode for ldarg.0 */
0x03, /* 03h is the opcode for ldarg.1 */
0x58, /* 58h is the opcode for add */
0x2A /* 2Ah is the opcode for ret */
};
来自类中定义的方法,例如:
public class MethodBodyDemo
{
public int Add(int x, int y)
{
return x + y;
}
}
我尝试了以下调用来填充字节数组:
var ILcodes = typeof(MethodBodyDemo).GetMethod("Add").GetMethodBody().GetILAsByteArray();
以下是我正在创建的示例,但它给出了一个例外: “Common Language Runtime 检测到无效程序。”
public class MethodBodyDemo
{
public int Add(int x, int y)
{
return x + y;
}
// This class will demonstrate how to create a method body using
// the MethodBuilder.CreateMethodBody(byte[], int) method.
public static Type BuildDynType()
{
Type addType = null;
AppDomain currentDom = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.RunAndSave);
// The dynamic assembly space has been created. Next, create a module
// within it. The type Point will be reflected into this module.
ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule("MyModule");
TypeBuilder myTypeBldr = myModuleBldr.DefineType("Adder");
MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("Add",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(int),
new Type[]
{typeof(int), typeof(int)});
// Build the array of Bytes holding the MSIL instructions.
// byte[] ILcodes = new byte[] {
// 0x02, /* 02h is the opcode for ldarg.0 */
// 0x03, /* 03h is the opcode for ldarg.1 */
// 0x58, /* 58h is the opcode for add */
// 0x2A /* 2Ah is the opcode for ret */
//};
var ILcodes = typeof(MethodBodyDemo).GetMethod("Add").GetMethodBody().GetILAsByteArray();
myMthdBldr.CreateMethodBody(ILcodes, ILcodes.Length);
addType = myTypeBldr.CreateType();
return addType;
}
public static void TestExecMethod()
{
Type myType = BuildDynType();
Console.WriteLine("---");
Console.Write("Enter the first integer to add: ");
int aVal = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the second integer to add: ");
int bVal = Convert.ToInt32(Console.ReadLine());
object adderInst = Activator.CreateInstance(myType, new object[0]);
Console.WriteLine("The value of adding {0} to {1} is: {2}.",
aVal, bVal,
myType.InvokeMember("Add",
BindingFlags.InvokeMethod,
null,
adderInst,
new object[] { aVal, bVal }));
}
}
通过调用执行:
MethodBodyDemo.TestExecMethod();
有什么帮助吗?
【问题讨论】:
-
只是出于好奇,你到底想做什么? :) 直接调用方法(或间接使用反射)或使用
System.Reflection.Emit.ILGenerator创建指令有什么问题吗? -
我有点困惑——你基本上是在尝试动态地向一个对象添加一个新方法然后调用它吗?
-
我正在寻找的是复制一个方法将它发送到另一个系统并且该系统执行它,但另一个系统不知道正在使用的库。上面的代码都是这样做的,唯一的问题是如何填写ILcode?span>
-
有趣的方法,某种验证器/反盗版或只是无聊?如果不是什么秘密,您可以从文本中执行 C# 代码或动态加载程序集/在库上使用 MEF。
-
你的最终目标是不可能的;字节码包含编译时生成的元数据标记。我上次检查(2010 年)时,它们根据编译器找到它们的顺序递增数字。调用 String.Join 可能会在您的代码中解析为令牌 0A000001,但在您的目标计算机上可能是 0A000009。或者,如果您的目标计算机未在其程序集中调用该方法,它甚至可能不作为元数据令牌存在。您需要将字节数组转换为收件人可以自行编译/解析的格式。有点相关:stackoverflow.com/a/3193423
标签: c# reflection cil methodinfo