我正在编写Mono.Cecil代码处理程序,我想预编如下操作:
Loop through types
If type contains X attribute:
- Add ITestInterface implementation (where ITestInterface has defined some methods)// 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等效或解决方法&如何使用它?
发布于 2021-08-06 03:08:12
这可以通过以下方式实现:
举个例子,您可以这样做:
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#的信息:
https://stackoverflow.com/questions/68651680
复制相似问题