c# - 将 Reflection.Emit 转换为 Roslyn

标签 c# roslyn reflection.emit

我需要将使用 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}";
    }
}

关于c# - 将 Reflection.Emit 转换为 Roslyn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38067666/

相关文章:

使用 Telerik ASP MVC 的动态模型

c# - 旋转 3D 坐标

c# - 链接标签打不开

c# - 有没有办法告诉路由我的默认操作名称等于 HTTP 操作动词?

Roslyn - 将字符串解析为 MethodDeclarationSyntax

.net - 发出操作码将字段设置为一个值

c# - 发出局部变量并为其赋值

c# - 检查字符串中是否有任何连续的重复子字符串

c# - 仅在“编辑并继续”中出现错误 CS7038(无法发出模块)

c# - 如何计算 lambda 表达式和匿名方法的嵌套数量?