2014-10-10 35 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 – 2014-10-10 17:08:39

回答

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... 
    } 
} 

現在我們剛剛創建的AssemblyB一類是試圖調用其他程序集的private static方法。如果它直接用C#編寫,它可能看起來像這樣。

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

由於CompilerGeneratedMethodprivate它不能被訪問。因此,我們嘗試使用真正的public方法,而不是使用lamda。

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來調用靜態方法,該方法應該用於後期綁定方法。我們應該只使用Call而不是Callvirt

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

我不能創建一個真正的公共方法,由於映射器意由外部庫使用,所以方法的名稱是不知道的。 – nohros 2014-10-10 20:02:51