2013-02-04 80 views
2

我正在嘗試使用Reflection.Emit來發出一個類,該類將在運行時從多個接口繼承,並且我無法提前知道哪些接口。 發送一個類覆蓋兩個同名的接口方法

作爲每MSDN/TypeBuilder.DefineMethodOverride

要覆蓋的基類的方法或實現一個 界面的方法,簡單地發射的方法具有相同的名稱和簽名作爲 被覆蓋的方法或實施

這裏是我的代碼重寫的接口方法:

private void OverrideMethod(TypeBuilder typeBuilder, 
          Type interfaceToOverride, 
          MethodInfo methodToOverride) 
{ 
    // Create the method stub 
    MethodBuilder methodBuilder = typeBuilder.DefineMethod(
     methodToOverride.Name, 
     MethodAttributes.Public 
     | MethodAttributes.HideBySig 
     | MethodAttributes.NewSlot 
     | MethodAttributes.Virtual 
     | MethodAttributes.Final, 
     CallingConventions.HasThis, 
     methodToOverride.ReturnType, 
     methodToOverride.GetParameters().Select(p => p.ParameterType).ToArray() 
    ); 

    // Implement the overriding method 
    ILGenerator il = methodBuilder.GetILGenerator(); 

    // ... a bunch of calls to il.Emit ... 

    // Return 
    il.Emit(OpCodes.Ret); 
} 

這是有效的,除非我從兩個接口都有同名的方法繼承。很明顯,這是因爲我沒有爲該方法提供完全合格的名稱。我不知道如何正確執行此操作。

更改methodToOverride.NameinterfaceToOverride.FullName + "." + methodToOverride.Name沒有工作:發射時,我得到一個錯誤,「TypeLoadException:類沒有實現

使用DefineMethodOverride部分工作,但由於某種原因沒有當我測試了它反對嵌套接口。另外,上面明確鏈接的文件說,不要這樣做。

什麼是正確的方法來解決這個問題?

+2

閱讀[DefineMethodOverride'的MSDN頁面](http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.definemethodoverride%28VS.95%29.aspx)似乎表明這是您需要用來定義顯式聲明的接口實現的機制。也許你可以發佈你定義它的代碼並在你的測試中調用它? –

+0

@Chris:也許我誤解了它們的意思,「不要使用此方法來發出方法覆蓋或接口實現。」 (鏈接中的第一句話。)這聽起來正是我想要在這裏做的。 –

+1

@notfed - 我相信他們的意思是你不應該使用'DefineMethodOverride'來定義隱式的接口實現。但是,我相信這是創建接口實現的唯一方法,其中方法的名稱與接口使用的方法的名稱不同。 – kvb

回答

2

做到這一點,正確的方法是定義一個方法命名<InterfaceName>.<MethodName>,然後調用TypeBuilder.DefineMethodOverride

的DefineMethodOverride方法用於當方法本體和 方法聲明具有不同的名稱

你的情況,方法體名稱是<InterfaceName>.<MethodName>,而方法聲明名稱是<MethodName>。所以可以使用TypeBuilder.DefineMethodOverride

用法示例

private void OverrideMethod(TypeBuilder typeBuilder, 
          Type interfaceToOverride, 
          MethodInfo methodToOverride) 
{ 
    // Create the method stub 
    MethodBuilder methodBuilder = typeBuilder.DefineMethod(
     /* Change method name here */ 
     string.Format("{0}.{1}", interfaceToOverride.FullName, 
      methodToOverride.Name), 
     MethodAttributes.Public 
     | MethodAttributes.HideBySig 
     | MethodAttributes.NewSlot 
     | MethodAttributes.Virtual 
     | MethodAttributes.Final, 
     CallingConventions.HasThis, 
     methodToOverride.ReturnType, 
     methodToOverride.GetParameters().Select(p => p.ParameterType).ToArray() 
    ); 

    // Implement the overriding method 
    ILGenerator il = methodBuilder.GetILGenerator(); 

    // ... a bunch of calls to il.Emit ... 

    // Return 
    il.Emit(OpCodes.Ret); 

    // And define a methodimpl, which consists of a pair of metadata tokens. 
    // One token points to an implementation, and the other token points 
    // to a declaration that the body implements 
    typeBuilder.DefineMethodOverride(methodBuilder, methodToOverride); 
} 

注意

其實,你可以定義你的方法(使用TypeBuilder.DefineMethod)與任何名。但它應該與<MethodName>有所不同,而您的必須請致電TypeBuilder.DefineMethodOverride將方法主體與方法聲明「鏈接」。

相關問題