繁体   English   中英

将Reflection.Emit转换为Roslyn

[英]Convert Reflection.Emit to Roslyn

我需要将使用Reflection.Emit的现有代码转换为Roslyn。

我目前的代码基本上是这样的:

var assemblyName = new AssemblyName("AssemblyName");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);

var builder = assemblyBuilder.DefineDynamicModule("test", "test.dll");

var type = builder.DefineType("Entry", TypeAttributes.Public, typeof(object), null);

var method = type.DefineMethod("###Start_v1.4.3.0", MethodAttributes.Public | MethodAttributes.HideBySig);
method.SetReturnType(typeof(void));

var generator = method.GetILGenerator();

generator.Emit(OpCodes.Nop);
generator.Emit(OpCodes.Ret);

type.CreateType();

assemblyBuilder.Save(@"test.dll");

如您所见,有一个名为Entry的类,其方法名为###Start_v1.4.3.0

我们现在使用它超过7年了,但是我们需要改变任何东西,这是一种痛苦,因为我们需要使用那些Emits而且它不是微不足道的。

如果我们可以让Roslyn编译代码会很棒:

public class Entry
{
    public void ###Start_v1.4.3.0()
    {
    }
}

但由于方法名称无效,它无效。

编译的dll由第三方组件使用,它查找要执行的类和方法名称。 我们试图让开发人员有一个新版本,但没有运气。

我认为Roslyn根本不会编译它,但我相信可能有一种方法可以稍后重命名方法名称,让我们说只需要Start()###Start_v1.4.3.0() ...我只是不要我知道怎么做。

任何帮助都将非常受欢迎。

如果唯一的问题是非法方法名称,则可以轻松解决该问题。

使用合法名称编译dll,然后您可以通过多种方法更改方法名称。

使用mono.cecil非常简单。

public void ChangeMethodName()
{
    //Before changing the method name
    var assem = Assembly.LoadFile(@"C:\temp\ClassLibrary1.dll");
    Console.WriteLine(
        assem.GetType("ClassLibrary1.Class1").
        GetMethod("Start", BindingFlags.Static | BindingFlags.Public).
        Invoke(null, null));

    // Change the name
    var module = ModuleDefinition.ReadModule(@"C:\temp\ClassLibrary1.dll");
    TypeDefinition myType = 
        module.Types.First(type => type.Name == "Class1");
    var method = myType.Methods.First(m => m.Name == "Start");
    method.Name = "###Start_v1.4.3.0";
    module.Write(@"C:\temp\ClassLibrary1_new.dll");

    //After changing the method name
    assem = Assembly.LoadFile(@"C:\temp\ClassLibrary1_new.dll");
    Console.WriteLine(
        assem.GetType("ClassLibrary1.Class1").
        GetMethod("###Start_v1.4.3.0",
                  BindingFlags.Static|BindingFlags.Public).
        Invoke(null, null));
}



public class Class1
{
    public static string Start()
    {
        return $"my name is {MethodBase.GetCurrentMethod().Name}";
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM