2016-06-28 3 views
2

Reflection.Emit을 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"); 

###Start_v1.4.3.0라는 방법 Entry라는 이름의 클래스가있다.

우리는 이것을 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}"; 
    } 
}