gpt4 book ai didi

c# - 从动态创建的类中调用构造函数和方法

转载 作者:太空宇宙 更新时间:2023-11-03 14:57:40 25 4
gpt4 key购买 nike

我正在使用 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.NewobjOpCodes.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") 来调用 GetConstructorGetMethod

最佳答案

创建程序集:

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);
}

现在创建主类:

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”打印到标准输出

关于c# - 从动态创建的类中调用构造函数和方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48140433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com