我想使用单声道。塞西尔创建一个委托,但我不知道如何获得它的构造函数
I want to use Mono. Cecil to create a delegate, but I don't know how to get its constructor
我希望能够为代码生成 il
InjectBake.AddConstruction(typeof(Tests.TestConst), new Func<object[], IServiceProvider, object>[]
{
Test1,
Test2
});
我在反编译中看到这段代码,我不知道如何构造它,
newobj instance void class [mscorlib]System.Func`3<object[], class [mscorlib]System.IServiceProvider, object>::.ctor(object, native int)
假设您要生成以下 class:
using System;
class Test
{
static string M(int i) { return i.ToString(); }
void Foo()
{
Func conv = M;
}
}
您可以使用Cecilifier生成以下代码:
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using System;
using System.Linq;
using BindingFlags = System.Reflection.BindingFlags;
using Cecilifier.Runtime;
public class SnippetRunner
{
public static void Main(string[] args)
{
using(var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("Test", Version.Parse("1.0.0.0")), "moduleName", ModuleKind.Dll))
{
var t1 = new TypeDefinition("", "Test", TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.NotPublic, assembly.MainModule.TypeSystem.Object);
assembly.MainModule.Types.Add(t1);
t1.BaseType = assembly.MainModule.TypeSystem.Object;
var Test_ctor_ = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, assembly.MainModule.TypeSystem.Void);
t1.Methods.Add(Test_ctor_);
var il1 = Test_ctor_.Body.GetILProcessor();
var Ldarg_02 = il1.Create(OpCodes.Ldarg_0);
il1.Append(Ldarg_02);
var Call3 = il1.Create(OpCodes.Call, assembly.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(t1.BaseType)));
il1.Append(Call3);
var Ret4 = il1.Create(OpCodes.Ret);
il1.Append(Ret4);
//Method : M
var Test_M_int32 = new MethodDefinition("M", MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.String);
t1.Methods.Add(Test_M_int32);
var il_Test_M_int32 = Test_M_int32.Body.GetILProcessor();
//Parameters of 'static string M(int i) { return i.ToString(); }'
var i5 = new ParameterDefinition("i", ParameterAttributes.None, assembly.MainModule.TypeSystem.Int32);
Test_M_int32.Parameters.Add(i5);
//return i.ToString();
var Ldarga6 = il_Test_M_int32.Create(OpCodes.Ldarga, i5);
il_Test_M_int32.Append(Ldarga6);
var Call7 = il_Test_M_int32.Create(OpCodes.Call, assembly.MainModule.ImportReference(TypeHelpers.ResolveMethod("System.Private.CoreLib", "System.Int32", "ToString",System.Reflection.BindingFlags.Default|System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public,"")));
il_Test_M_int32.Append(Call7);
var Ret8 = il_Test_M_int32.Create(OpCodes.Ret);
il_Test_M_int32.Append(Ret8);
//Method : Foo
var Test_Foo_ = new MethodDefinition("Foo", MethodAttributes.Private | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.Void);
t1.Methods.Add(Test_Foo_);
var il_Test_Foo_ = Test_Foo_.Body.GetILProcessor();
//Func<int, string> conv = M;
var lv_conv9 = new VariableDefinition(assembly.MainModule.ImportReference(typeof(System.Func<,>)).MakeGenericInstanceType(assembly.MainModule.TypeSystem.Int32,assembly.MainModule.TypeSystem.String));
Test_Foo_.Body.Variables.Add(lv_conv9);
var Ldnull10 = il_Test_Foo_.Create(OpCodes.Ldnull);
il_Test_Foo_.Append(Ldnull10);
var Ldftn11 = il_Test_Foo_.Create(OpCodes.Ldftn, Test_M_int32);
il_Test_Foo_.Append(Ldftn11);
var Newobj12 = il_Test_Foo_.Create(OpCodes.Newobj, assembly.MainModule.ImportReference(TypeHelpers.ResolveMethod("System.Private.CoreLib", "System.Func`2", ".ctor",System.Reflection.BindingFlags.Default|System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public,"System.Int32,System.String", "System.Object", "System.IntPtr")));
il_Test_Foo_.Append(Newobj12);
var Stloc13 = il_Test_Foo_.Create(OpCodes.Stloc, lv_conv9);
il_Test_Foo_.Append(Stloc13);
var Ret14 = il_Test_Foo_.Create(OpCodes.Ret);
il_Test_Foo_.Append(Ret14);
PrivateCoreLibFixer.FixReferences(assembly.MainModule);
assembly.Write(args[0]);
}
}
}
简单来说,您需要:
获取您要更改/添加代码的方法定义。 (第 48 行)
获取该方法的 ILProcessor(第 50 行)
注入 NewObj IL(第 59 行)
第 3 步是最重要的:
var Newobj12 = il_Test_Foo_.Create(
OpCodes.Newobj,
assembly.MainModule.ImportReference(
TypeHelpers.ResolveMethod(
"System.Private.CoreLib",
"System.Func`2",
".ctor",
System.Reflection.BindingFlags.Default|System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public,
"System.Int32,System.String",
"System.Object",
"System.IntPtr")));
基本上它只是调用 ILProcessor.Create() 传递:
- 您要创建的操作码(指令)(在本例中为 Newobj)
- 对要实例化的对象的构造函数的引用。
对于上面的第 2 步,Cecilifier 使用辅助函数 TypeHelpers.ResolveMethod(),它基本上使用反射来检索方法并将其传递给 ModuleDefinition.ImportReference()
。
我希望能够为代码生成 il
InjectBake.AddConstruction(typeof(Tests.TestConst), new Func<object[], IServiceProvider, object>[]
{
Test1,
Test2
});
我在反编译中看到这段代码,我不知道如何构造它,
newobj instance void class [mscorlib]System.Func`3<object[], class [mscorlib]System.IServiceProvider, object>::.ctor(object, native int)
假设您要生成以下 class:
using System;
class Test
{
static string M(int i) { return i.ToString(); }
void Foo()
{
Func conv = M;
}
}
您可以使用Cecilifier生成以下代码:
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using System;
using System.Linq;
using BindingFlags = System.Reflection.BindingFlags;
using Cecilifier.Runtime;
public class SnippetRunner
{
public static void Main(string[] args)
{
using(var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("Test", Version.Parse("1.0.0.0")), "moduleName", ModuleKind.Dll))
{
var t1 = new TypeDefinition("", "Test", TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.NotPublic, assembly.MainModule.TypeSystem.Object);
assembly.MainModule.Types.Add(t1);
t1.BaseType = assembly.MainModule.TypeSystem.Object;
var Test_ctor_ = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, assembly.MainModule.TypeSystem.Void);
t1.Methods.Add(Test_ctor_);
var il1 = Test_ctor_.Body.GetILProcessor();
var Ldarg_02 = il1.Create(OpCodes.Ldarg_0);
il1.Append(Ldarg_02);
var Call3 = il1.Create(OpCodes.Call, assembly.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(t1.BaseType)));
il1.Append(Call3);
var Ret4 = il1.Create(OpCodes.Ret);
il1.Append(Ret4);
//Method : M
var Test_M_int32 = new MethodDefinition("M", MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.String);
t1.Methods.Add(Test_M_int32);
var il_Test_M_int32 = Test_M_int32.Body.GetILProcessor();
//Parameters of 'static string M(int i) { return i.ToString(); }'
var i5 = new ParameterDefinition("i", ParameterAttributes.None, assembly.MainModule.TypeSystem.Int32);
Test_M_int32.Parameters.Add(i5);
//return i.ToString();
var Ldarga6 = il_Test_M_int32.Create(OpCodes.Ldarga, i5);
il_Test_M_int32.Append(Ldarga6);
var Call7 = il_Test_M_int32.Create(OpCodes.Call, assembly.MainModule.ImportReference(TypeHelpers.ResolveMethod("System.Private.CoreLib", "System.Int32", "ToString",System.Reflection.BindingFlags.Default|System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public,"")));
il_Test_M_int32.Append(Call7);
var Ret8 = il_Test_M_int32.Create(OpCodes.Ret);
il_Test_M_int32.Append(Ret8);
//Method : Foo
var Test_Foo_ = new MethodDefinition("Foo", MethodAttributes.Private | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.Void);
t1.Methods.Add(Test_Foo_);
var il_Test_Foo_ = Test_Foo_.Body.GetILProcessor();
//Func<int, string> conv = M;
var lv_conv9 = new VariableDefinition(assembly.MainModule.ImportReference(typeof(System.Func<,>)).MakeGenericInstanceType(assembly.MainModule.TypeSystem.Int32,assembly.MainModule.TypeSystem.String));
Test_Foo_.Body.Variables.Add(lv_conv9);
var Ldnull10 = il_Test_Foo_.Create(OpCodes.Ldnull);
il_Test_Foo_.Append(Ldnull10);
var Ldftn11 = il_Test_Foo_.Create(OpCodes.Ldftn, Test_M_int32);
il_Test_Foo_.Append(Ldftn11);
var Newobj12 = il_Test_Foo_.Create(OpCodes.Newobj, assembly.MainModule.ImportReference(TypeHelpers.ResolveMethod("System.Private.CoreLib", "System.Func`2", ".ctor",System.Reflection.BindingFlags.Default|System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public,"System.Int32,System.String", "System.Object", "System.IntPtr")));
il_Test_Foo_.Append(Newobj12);
var Stloc13 = il_Test_Foo_.Create(OpCodes.Stloc, lv_conv9);
il_Test_Foo_.Append(Stloc13);
var Ret14 = il_Test_Foo_.Create(OpCodes.Ret);
il_Test_Foo_.Append(Ret14);
PrivateCoreLibFixer.FixReferences(assembly.MainModule);
assembly.Write(args[0]);
}
}
}
简单来说,您需要:
获取您要更改/添加代码的方法定义。 (第 48 行)
获取该方法的 ILProcessor(第 50 行)
注入 NewObj IL(第 59 行)
第 3 步是最重要的:
var Newobj12 = il_Test_Foo_.Create(
OpCodes.Newobj,
assembly.MainModule.ImportReference(
TypeHelpers.ResolveMethod(
"System.Private.CoreLib",
"System.Func`2",
".ctor",
System.Reflection.BindingFlags.Default|System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public,
"System.Int32,System.String",
"System.Object",
"System.IntPtr")));
基本上它只是调用 ILProcessor.Create() 传递:
- 您要创建的操作码(指令)(在本例中为 Newobj)
- 对要实例化的对象的构造函数的引用。
对于上面的第 2 步,Cecilifier 使用辅助函数 TypeHelpers.ResolveMethod(),它基本上使用反射来检索方法并将其传递给 ModuleDefinition.ImportReference()
。