C# Reflection.Emit.ILGenerator::Emit,从第三方.net库调用方法

C# Reflection.Emit.ILGenerator::Emit,从第三方.net库调用方法,c#,.net,compiler-construction,reflection.emit,C#,.net,Compiler Construction,Reflection.emit,我正在尝试创建简单的.net编译器,用于教育目的。在解析、扫描和构建AST之后,我将使用Reflection.Emit.ILGenerator生成.net程序集 以下是我生成程序集的示例代码: static void Main(string[] args) { string moduleName = "Test.exe"; AssemblyName assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(

我正在尝试创建简单的.net编译器,用于教育目的。在解析、扫描和构建AST之后,我将使用
Reflection.Emit.ILGenerator
生成.net程序集

以下是我生成程序集的示例代码:

static void Main(string[] args)
{
    string moduleName = "Test.exe";

    AssemblyName assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(moduleName));
    AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
    ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
    TypeBuilder typeBuilder = moduleBuilder.DefineType("Program", TypeAttributes.Public);
    MethodBuilder mainMethod = typeBuilder.DefineMethod(
        "Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void), System.Type.EmptyTypes);


    ILGenerator il = mainMethod.GetILGenerator();

    il.Emit(OpCodes.Ldstr, "Test!");
    il.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) }));
    il.Emit(OpCodes.Ret);

    typeBuilder.CreateType();
    moduleBuilder.CreateGlobalFunctions();
    assemblyBuilder.SetEntryPoint(mainMethod);
    assemblyBuilder.Save(moduleName);
}
一切正常,此代码生成具有以下类的可执行文件:

using System;

public class Program
{
    public Program()
    {
    }

    public static void Main()
    {
        Console.WriteLine("Test!");
    }
}
接下来,我将创建一个简单的第三方库,其中有一个类构建到ThirdPartyLibrary.dll:

using System;

namespace ThirdPartyLibrary
{
    public class MyPrint
    {
        public static void Print(string s)
        {
            Console.WriteLine("Third party prints: " + s);
        }
    }
}
现在,我希望替换
控制台.WriteLine
方法调用到
MyPrint.Print
方法调用,从我的库中获取类似以下内容的结果代码:

using System;
using ThirdPartyLibrary;

public class Program
{
    public Program()
    {
    }

    public static void Main()
    {
        MyPrint.Print("Test!");
    }
}
据我所知,我必须阅读我的
ThirdPartyLibrary.dll
文件,然后以某种方式反映它以从中获取所有类型,然后才能使用
MyPrint
类型。最后,我希望能够像使用csc.exe一样,将引用作为myCompiler.exe参数进行路径设置

所以问题是:

  • 怎么做
  • 这一切是怎么命名的?(我不明白谷歌应该做什么)
  • 也许我应该使用一些其他的框架,而不是反射来完成这一切
  • 任何其他建议

这里唯一的变化是目标方法:

var targetMethod = Assembly.LoadFrom("ThirdPartyLibrary.dll")
    .GetType("ThirdPartyLibrary.MyPrint")
    .GetMethod("Print", new [] {typeof(string)});
...
il.Emit(OpCodes.Ldstr, "Test!");
il.Emit(OpCodes.Call, targetMethod);
il.Emit(OpCodes.Ret);
因此,我们不使用
Console.WriteLine
,而是调用
MyPrint.Print

  • 怎么做?A:如上所述
  • 这一切是怎么命名的?答:IL生成、元编程、反射
  • 也许我应该使用一些其他的框架,而不是反射来完成这一切?答:反思涵盖了大多数场景;我在一些地方使用了
    IKVM.Reflection.dll
    ,因为它允许我进行跨框架目标定位,但您可能不需要这样做。您可能会发现方便的是,在生成时(而不是在执行时)为您提供合理的错误报告,从而消除了IL生成的许多痛苦(不平衡的堆栈等)。塞西尔也很有趣

真的很酷!我没想到从dll获取类型这么简单。谢谢