从动态创建的调用构造函数和方法 类
Call constructors and methods from dynamically created classes
我正在使用 Cecil 创建动态程序集。如何在发出操作码时调用其构造函数或方法?
class Test
{
public static void Main(string[] args)
{
System.Console.WriteLine(new SomeClass().SomeMethod());
}
}
class SomeClass
{
public int SomeMethod() { return 0; }
}
如您所见,我需要 2 条 WriteLine 方法说明 - OpCodes.Newobj
和 OpCodes.Call
:
var assembly = AssemblyDefinition.CreateAssembly ( ... );
...
var mainMethod = new MethodDefinition( ... );
var ilProcessor = mainMethod.Body.GetILProcessor();
...
ilProcessor.Create(
OpCodes.Newobj,
assembly.MainModule.ImportReference(/* typeof("SomeClass") */
.GetConstructor(Type.EmptyTypes)));
ilProcessor.Create(
OpCodes.Call,
assembly.MainModule.ImportReference(/* typeof("SomeClass") */
.GetMethod("SomeMethod", Type.EmptyTypes)));
我该怎么做才能模仿 typeof("SomeClass")
调用 GetConstructor
和 GetMethod
?
创建程序集:
var moduleName = "Test.exe";
var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition(moduleName, new Version(1, 0, new Random().Next(1000))), moduleName, ModuleKind.Console);
var module = assembly.MainModule;
创建第一个类型:
TypeDefinition someClass;
MethodDefinition someMethod;
{
someClass = new TypeDefinition("ConsoleDemo", "SomeClass", TypeAttributes.Class | TypeAttributes.Public, module.TypeSystem.Object);
someMethod = new MethodDefinition("SomeMethod", MethodAttributes.Public, module.TypeSystem.Int32);
someMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
someMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
someClass.Methods.Add(someMethod);
var someClassCtor = new MethodDefinition(".ctor", MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, module.TypeSystem.Void);
someClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
someClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, objCtor));
someClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
someClass.Methods.Add(someClassCtor);
module.Types.Add(someClass);
}
现在创建主class:
var testClass = new TypeDefinition("ConsoleDemo", "Test", TypeAttributes.Class | TypeAttributes.Public, module.TypeSystem.Object);
var mainMethod = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, module.TypeSystem.Void);
mainMethod.Parameters.Add(new ParameterDefinition("args", ParameterAttributes.None, new ArrayType(module.TypeSystem.String)));
var writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
var importedMethod = module.Import(writeLineMethod);
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Newobj, someClass.GetConstructors().First()));
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Call, someMethod));
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Call, importedMethod));
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
testClass.Methods.Add(mainMethod);
var mainClassCtor = new MethodDefinition(".ctor", MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, module.TypeSystem.Void);
mainClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
mainClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, objCtor));
mainClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
testClass.Methods.Add(mainClassCtor);
module.Types.Add(testClass);
不要忘记设置入口点:
module.EntryPoint = mainMethod;
现在可以保存了:
assembly.Write(moduleName);
在 运行 之后,它按预期将“0”打印到标准输出
我正在使用 Cecil 创建动态程序集。如何在发出操作码时调用其构造函数或方法?
class Test
{
public static void Main(string[] args)
{
System.Console.WriteLine(new SomeClass().SomeMethod());
}
}
class SomeClass
{
public int SomeMethod() { return 0; }
}
如您所见,我需要 2 条 WriteLine 方法说明 - OpCodes.Newobj
和 OpCodes.Call
:
var assembly = AssemblyDefinition.CreateAssembly ( ... );
...
var mainMethod = new MethodDefinition( ... );
var ilProcessor = mainMethod.Body.GetILProcessor();
...
ilProcessor.Create(
OpCodes.Newobj,
assembly.MainModule.ImportReference(/* typeof("SomeClass") */
.GetConstructor(Type.EmptyTypes)));
ilProcessor.Create(
OpCodes.Call,
assembly.MainModule.ImportReference(/* typeof("SomeClass") */
.GetMethod("SomeMethod", Type.EmptyTypes)));
我该怎么做才能模仿 typeof("SomeClass")
调用 GetConstructor
和 GetMethod
?
创建程序集:
var moduleName = "Test.exe";
var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition(moduleName, new Version(1, 0, new Random().Next(1000))), moduleName, ModuleKind.Console);
var module = assembly.MainModule;
创建第一个类型:
TypeDefinition someClass;
MethodDefinition someMethod;
{
someClass = new TypeDefinition("ConsoleDemo", "SomeClass", TypeAttributes.Class | TypeAttributes.Public, module.TypeSystem.Object);
someMethod = new MethodDefinition("SomeMethod", MethodAttributes.Public, module.TypeSystem.Int32);
someMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
someMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
someClass.Methods.Add(someMethod);
var someClassCtor = new MethodDefinition(".ctor", MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, module.TypeSystem.Void);
someClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
someClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, objCtor));
someClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
someClass.Methods.Add(someClassCtor);
module.Types.Add(someClass);
}
现在创建主class:
var testClass = new TypeDefinition("ConsoleDemo", "Test", TypeAttributes.Class | TypeAttributes.Public, module.TypeSystem.Object);
var mainMethod = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, module.TypeSystem.Void);
mainMethod.Parameters.Add(new ParameterDefinition("args", ParameterAttributes.None, new ArrayType(module.TypeSystem.String)));
var writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
var importedMethod = module.Import(writeLineMethod);
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Newobj, someClass.GetConstructors().First()));
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Call, someMethod));
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Call, importedMethod));
mainMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
testClass.Methods.Add(mainMethod);
var mainClassCtor = new MethodDefinition(".ctor", MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, module.TypeSystem.Void);
mainClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
mainClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, objCtor));
mainClassCtor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
testClass.Methods.Add(mainClassCtor);
module.Types.Add(testClass);
不要忘记设置入口点:
module.EntryPoint = mainMethod;
现在可以保存了:
assembly.Write(moduleName);
在 运行 之后,它按预期将“0”打印到标准输出