首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mono.Cecil AddInterfaceImplementation等效?

Mono.Cecil AddInterfaceImplementation等效?
EN

Stack Overflow用户
提问于 2021-08-04 12:58:29
回答 1查看 127关注 0票数 1

我正在编写Mono.Cecil代码处理程序,我想预编如下操作:

代码语言:javascript
复制
Loop through types
If type contains X attribute:
- Add ITestInterface implementation (where ITestInterface has defined some methods)
代码语言:javascript
复制
// For reference

public interface ITestInterface
{
    void Something();
    int IntSomething();
}

// Expected result, if type contains X attribute:
// Before codegen:
[X]
public class CodeGenExample
{
}

// After codegen
[X]
public class CodeGenExample : ITestInterface
{
   public void Something()
   {
       // some stuff
   }

   public int IntSomething()
   {
       // do some stuff
       return 0;
   }
}

我已经看到.NET反射有一个AddInterfaceImplementation方法(https://learn.microsoft.com/pl-pl/dotnet/api/system.reflection.emit.typebuilder.addinterfaceimplementation?view=net-5.0)。

对于这一点,是否存在Mono.Cecil等效或解决方法&如何使用它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-06 03:08:12

这可以通过以下方式实现:

  1. 迭代程序集中定义的所有类型。
  2. 检查应用于哪些类型的属性
  3. 注射这些方法。

举个例子,您可以这样做:

代码语言:javascript
复制
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace inject
{
    interface IMyInterface 
    {
        int Something();
    }

    class MarkerAttribute : Attribute {}

    [Marker]
    class Foo
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                using var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
                var interfaceToImplement = a.MainModule.GetType("inject.IMyInterface");

                foreach(var t in a.MainModule.Types)
                {
                    if (t.HasCustomAttributes && t.CustomAttributes.Any(c => c.Constructor.DeclaringType.Name == "MarkerAttribute"))
                    {
                        System.Console.WriteLine($"Adding methods to : {t}");
                        
                        var something = new MethodDefinition("Something", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, a.MainModule.TypeSystem.Int32);
                        something.Body = new Mono.Cecil.Cil.MethodBody(something);
                        var il = something.Body.GetILProcessor();

                        il.Emit(OpCodes.Ldc_I4, 42);
                        il.Emit(OpCodes.Ret);
                        t.Methods.Add(something);


                        // Add the interface.
                        t.Interfaces.Add(new InterfaceImplementation(interfaceToImplement));

                        var path  = typeof(Program).Assembly.Location + ".new";
                        a.Write(path);

                        System.Console.WriteLine($"Modified version written to {path}");
                    }
                }
            }
            else
            {           
                object f = new Foo();
                IMyInterface itf = (IMyInterface) f;
                System.Console.WriteLine($"Something() == {itf.Something()}");
            }
        }
    }
}

另一个潜在的解决方案是让方法在内部类中实现,并对它们的方法体进行复制。

另外,您可以使用以下两个在线工具来探索/了解更多关于CIL、Mono.Cecil、C#的信息:

  1. Sharplab.io
  2. 纤毛器 (免责声明:我是这篇文章的作者)

尽管如此,如果您可以使用C# 9.0,您可能能够利用新的源发生器 功能

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68651680

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档