将反射.向罗斯林发射

本文关键字:发射 罗斯林 反射 | 更新日期: 2023-09-27 17:51:22

我需要转换使用反射的现有代码。向罗斯林发射。

我现在的代码基本上是这样的:

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}";
    }
}