2014-10-10 3 views
1

동적으로 생성 된 어셈블리의 "일반"어셈블리에있는 메서드를 호출 할 수 있습니까?동적 어셈블리에서 영구 어셈블리에 대한 메서드 실행

예를 들어, 어셈블리 B가 동적 조립체 (A) 및 어셈블리에서 (발광 통해) 구성되는 B지도 방법은 MissingMethodExcetion 실행될 때 어셈블리 A.

public interface IMapper 
{ 
    void Map(); 
} 

public void CreateDynamic() { 
    AppDomain app = AppDomain.CurrentDomain; 
    AssemblyName name = new AssemblyName("assemblyB"); 
    AssemblyBuilder assembly = app 
    .DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); 
    ModuleBuilder module = assembly 
    .DefineDynamicModule(assembly.GetName().Name, "b.dll"); 

    TypeBuilder type = module.DefineType("MyType", 
    TypeAttributes.Public | 
     TypeAttributes.Class | 
     TypeAttributes.AutoClass | 
     TypeAttributes.AutoLayout, null, new[] {typeof (IMapper)}); 

    MethodBuilder method = type 
    .DefineMethod("Map", 
     MethodAttributes.Public | 
     MethodAttributes.HideBySig | 
     MethodAttributes.Virtual); 

    ILGenerator il = method.GetILGenerator(); 

    Func<int, TimeSpan> func = i => TimeSpan.FromSeconds(i); 

    il.Emit(OpCodes.Ldc_I4_S, 10); 
    il.Emit(OpCodes.Callvirt, func.Method); 
    il.Emit(OpCodes.Ret); 

    Type t = type.CreateType(); 

    IMapper mapper = (IMapper) Activator.CreateInstance(t); 
    mapper.Map(); 
} 

에 정의 된 정적 메소드를 호출해야 나는 던져져 이제는 그 이유가되지 않습니다.

+0

, 코드 샘플을 제공 및/또는 내가 진짜 공공의 방법을 만들 수 없습니다이 http://stackoverflow.com/questions/11908156/call-static-method-with-reflection –

답변

1

아래 라인을 컴파일하면 컴파일시에 private static 메서드가 생성됩니다.

Func<int, TimeSpan> func = i => TimeSpan.FromSeconds(i); 

그래서 무엇을하려는 것입니까?

public class TestClass { 
    private static TimeSpan CompilerGeneratedMethod(int i) { 
     return TimeSpan.FromSeconds(i); 
    } 

    public void CreateDynamic() { 
     // Other codes... 

     var methodInfo = typeof(TestClass).GetMethod("CompilerGeneratedMethod", BindingFlags.Static | BindingFlags.NonPublic); 

     il.Emit(OpCodes.Ldc_I4_S, 10); 
     il.Emit(OpCodes.Callvirt, methodInfo); 
     il.Emit(OpCodes.Ret); 

     // Other codes... 
    } 
} 

이제 우리는 또 다른 어셈블리의 private static 메소드를 호출하려고 AssemblyB의 클래스를 만들었습니다. C#으로 직접 작성된 경우 다음과 같이 보일 수 있습니다. CompilerGeneratedMethod 이후

public class MyType : IMapper { 
    public void Map() { 
     TestClass.CompilerGeneratedMethod(10); 
    } 
} 

가 액세스 할 수없는 private이다. 따라서 lamda를 사용하는 대신 실제 선언 된 public 메서드를 사용해 보겠습니다.

public class TestClass { 
    public static TimeSpan HandWrittenMethod(int i) { 
     return TimeSpan.FromSeconds(i); 
    } 

    public void CreateDynamic() { 
     // Other codes... 

     var methodInfo = typeof(TestClass).GetMethod("HandWrittenMethod"); 

     il.Emit(OpCodes.Ldc_I4_S, 10); 
     il.Emit(OpCodes.Callvirt, methodInfo); 
     il.Emit(OpCodes.Ret); 

     // Other codes... 
    } 
} 

이제는 사소한 문제점이 있습니다. 늦게 바인딩 된 메서드에 사용해야하는 Callvirt을 사용하여 정적 메서드를 호출하려고합니다. Callvirt 대신 Call을 사용해야합니다. 매퍼가 구성되어 있기 때문에

il.Emit(OpCodes.Call, methodInfo); 
+0

을 확인 외부 라이브러리에서 사용할 수 있으므로 메서드 이름은 미리 알 수 없습니다. – nohros