使用Mono.Cecil在C#程序集中注入方法

时间:2017-03-02 20:36:14

标签: c# .net mono mono.cecil

我正在开发一些.Net应用程序,我需要使用自己的代码注入任何汇编新方法。我正在使用Mono.Cecil来获取装配体,我发现了一些样品,但它们已经足够老了。不幸的是,github wiki上的migraton部分没有任何信息。

所以,我有这段代码:

using System; 
using Mono.Cecil; 
using Mono.Cecil.Cil; 

namespace CustomFieldsInjection 
{ 
    public partial class Injector 
    { 
        public static void MethodInjection(string assemblyFilename, string typeName, string methodName) 
        { 
            AssemblyDefinition assembly = AssemblyFactory.GetAssembly(assemblyFilename); 

            TypeReference returnTypeReference = assembly.MainModule.Import(typeof(void)); 

            MethodDefinition methodDefinition = new MethodDefinition(methodName, MethodAttributes.Public | MethodAttributes.Static, returnTypeReference); 

            Instruction instruction1 = methodDefinition.Body.CilWorker.Create(OpCodes.Nop); 

            Instruction instruction2 = methodDefinition.Body.CilWorker.Create(OpCodes.Ldstr, methodName); 

            MethodReference writeline = assembly.MainModule.Import(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); 

            methodDefinition.Body.CilWorker.Append(instruction1); 
            methodDefinition.Body.CilWorker.Append(instruction2); 

            methodDefinition.Body.CilWorker.InsertAfter(instruction2, methodDefinition.Body.CilWorker.Create (OpCodes.Call, writeline)); 

            methodDefinition.Body.CilWorker.Append (methodDefinition.Body.CilWorker.Create(OpCodes.Ret))

            assembly.MainModule.Inject(methodDefinition, assembly.MainModule.Types[typeName]); 
            MethodReference methodReference = null; 

            foreach (MethodDefinition method in assembly.MainModule.Types[typeName].Methods) 
            { 
                if (method.Name == methodName) 
                { 
                    methodReference = assembly.MainModule.Import(method); 
                    break; 
                } 
            } 

            Instruction callTest = methodDefinition.Body.CilWorker.Create(OpCodes.Call, methodReference); 

            if (assembly.EntryPoint != null) 
            { 
                assembly.EntryPoint.Body.CilWorker.InsertBefore(assembly.EntryPoint.Body.Instructions[0], callTest); 
            } 

            AssemblyFactory.SaveAssembly(assembly, assemblyFilename); 
        } 
    } 
} 

这是旧样本。大多数功能都是最新的。我对这个结构感兴趣:

assembly.MainModule.Inject(methodDefinition, assembly.MainModule.Types[typeName]);

我找不到这种设计的新类似物。有人可以告诉我它可以被替换吗?

1 个答案:

答案 0 :(得分:1)

我不熟悉您所指的构造,但在现有类型中添加MethodDefinition非常容易

using (var assemblyDefinition = AssemblyDefinition.ReadAssembly("assemblyPath")) {
    var module = AssemblyDefinition.MainModule;

    //Select the type you need to open for addition
    var typeDef = module.Types.First(td => td.Name == "footer");

    //Add your MethodDefinition
    typeDef.Methods.Add(your_method_definition);

    //Write the assembly back
    assemblyDefinition.Write();
}

注意:如果你还没有使用cecil 0.10.0.0,你将使用略有不同的ReadAssembly()Write()变体(没有using,并将assemblyPath传递给{{ 1}},主要是...)