2016-06-28 3 views
2

Мне нужно преобразовать существующий код, который использует Reflection.Emit to Roslyn.Convert Reflection.Emit to 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, и это не тривиально.

Было бы здорово, если бы мы могли просто Рослин компилировать код:

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

Но это не работает в связи с именем метода является недействительным.

Скомпилированная DLL-версия используется сторонним компонентом и ищет этот класс и имя метода. Мы попытались довести разработчиков до новой версии, но не повезло.

Я думаю, что Roslyn не будет компилировать это вообще, но я считаю, что может быть способ переименовать имя метода позже, скажем, только Start() - ###Start_v1.4.3.0() ... Я просто не знаю, как это сделать.

Любая помощь будет очень желанной.

+0

Я полагаю, вы могли бы использовать [ILDASM] (https://msdn.microsoft.com/en-us/library/f7dy01k1.aspx) и [ILASM] (https://msdn.microsoft.com/ en-us/library/496e4ekx.aspx) или Cecil для последующего патча. –

+0

Возможно, вам стоит задать запрос функции, чтобы разрешить имена произвольных членов. У CLR нет проблем с этими именами, и я не думаю, что в Roslyn что-то не удастся от этого. – usr

ответ

5

Если единственная проблема - это незаконное имя метода, вы можете легко решить эту проблему.

Скомпилируйте 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}"; 
    } 
}