将class方法转换为IL并在运行时执行
Convert class method into IL and execute it at runtime
我想将一个方法从class转换为IL代码,然后通过调用它来执行它。我正在关注的示例来自 msdn:https://msdn.microsoft.com/en-us/library/system.reflection.emit.methodbuilder.createmethodbody(v=vs.110).aspx.
它准确地显示了我所需要的,我的问题是从 class 方法生成 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 */
};
来自 class 中定义的方法,例如:
public class MethodBodyDemo
{
public int Add(int x, int y)
{
return x + y;
}
}
我尝试了以下调用来填充字节数组:
var ILcodes = typeof(MethodBodyDemo).GetMethod("Add").GetMethodBody().GetILAsByteArray();
以下是我正在创建的示例,但它给出了一个例外:
"Common Language Runtime detected an invalid program."
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();
有什么帮助吗?
以 Release
模式构建您的项目,并执行以下操作之一:
在此处删除 MethodAttributes.Static
属性
MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("Add",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(int),
new Type[]
{typeof(int), typeof(int)});
或将此方法更改为static
public int Add(int x, int y)
{
return x + y;
}
这应该适合你。
但是,我在评论中看到你希望它向其他系统传递字节并且 运行 它,我的回答只是针对你在题。事实上,这是行不通的,因为 Simon Svensson 在评论中写道。 (除非所有方法都是静态的并且只执行纯操作(如 return 3+4)而不引用其他 methods\types\fields。)
您仍然可以(理论上)施展魔法使其发挥作用,但实际上并不可行。
我是做类似事情的库的作者。它读取现有方法的操作码,将它们重新解释回包含 MethodInfo 而不是编号标记的通用操作码项,并从中构建一个方法副本。这适用于交叉组装,也适用于您的情况。
它被设计为猴子补丁游戏,但可以修改以将 "clear text" 中的通用操作码传输到不同的系统,以便目标可以进行类型查找,从而为本地程序集获取正确的操作码.
该项目已获得 MIT 许可,名为 Harmony。
我想将一个方法从class转换为IL代码,然后通过调用它来执行它。我正在关注的示例来自 msdn:https://msdn.microsoft.com/en-us/library/system.reflection.emit.methodbuilder.createmethodbody(v=vs.110).aspx.
它准确地显示了我所需要的,我的问题是从 class 方法生成 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 */
};
来自 class 中定义的方法,例如:
public class MethodBodyDemo
{
public int Add(int x, int y)
{
return x + y;
}
}
我尝试了以下调用来填充字节数组:
var ILcodes = typeof(MethodBodyDemo).GetMethod("Add").GetMethodBody().GetILAsByteArray();
以下是我正在创建的示例,但它给出了一个例外: "Common Language Runtime detected an invalid program."
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();
有什么帮助吗?
以 Release
模式构建您的项目,并执行以下操作之一:
在此处删除 MethodAttributes.Static
属性
MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("Add",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(int),
new Type[]
{typeof(int), typeof(int)});
或将此方法更改为static
public int Add(int x, int y)
{
return x + y;
}
这应该适合你。
但是,我在评论中看到你希望它向其他系统传递字节并且 运行 它,我的回答只是针对你在题。事实上,这是行不通的,因为 Simon Svensson 在评论中写道。 (除非所有方法都是静态的并且只执行纯操作(如 return 3+4)而不引用其他 methods\types\fields。)
您仍然可以(理论上)施展魔法使其发挥作用,但实际上并不可行。
我是做类似事情的库的作者。它读取现有方法的操作码,将它们重新解释回包含 MethodInfo 而不是编号标记的通用操作码项,并从中构建一个方法副本。这适用于交叉组装,也适用于您的情况。
它被设计为猴子补丁游戏,但可以修改以将 "clear text" 中的通用操作码传输到不同的系统,以便目标可以进行类型查找,从而为本地程序集获取正确的操作码.
该项目已获得 MIT 许可,名为 Harmony。