2015-05-02 106 views
4

警告:雖然接受的答案是正確的,任何人試圖實現這一點,請參閱@ CodesInChaos的意見爲好。對我來說這是一個壞主意。調用多個通用接口的類通過反射方式


我有一個通用的接口和實現的時間接口「N」數字類:

interface IA<T> 
{ 
    T Foo(); 
} 

class Baz1 { } 
class Baz2 { } 

class Bar : IA<Baz1>, IA<Baz2> 
{ 
    Baz1 Foo() { return new Baz1(); } 
    Baz2 Foo() { return new Baz2(); } 
} 

如何使用反射來調用上的Bar實例都Foo的方法呢?

我已經有下面的代碼來獲取接口定義和泛型類型參數:

class Frobber 
{ 
    void Frob(object frobbee) 
    { 
     var interfaces = frobbee.GetType() 
      .GetInterfaces() 
      .Where(i => i.IsGenericType && 
       i.GetGenericTypeDefinition() == typeof(IA<>).GetGenericTypeDefinition()); 
    } 
} 
+0

在我的具體情況,而不是'IA ',我有一個'Bar'類實現'IObservable ','IObservable '等等,還有'IObserver ','IObserver '等等,但我不想讓這個討論變成雲。也許這是相關的,但? –

+0

好吧,現在想想這個,* *實際上是相關的,因爲'IObservable '用例(在Baz上調用兩個不同的'Subscribe()'方法)不同於'IObserver '用例兩個不同的'Subscribe()'方法以'Baz'作爲參數)。所以讓我們考慮前者,就像我提供的示例代碼。 –

+1

你確定你想要繼承而不是組合嗎? – CodesInChaos

回答

4

定義:

interface IA<T> 
{ 
    T Foo(); 
} 

class Baz1 { } 
class Baz2 { } 

class Bar : IA<Baz1>, IA<Baz2> 
{ 
    Baz2 IA<Baz2>.Foo() 
    { 
     return new Baz2(); 
    } 

    Baz1 IA<Baz1>.Foo() 
    { 
     return new Baz1(); 
    } 
} 

代碼:

Bar b = new Bar(); 
    var methods = typeof(Bar).GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IA<>)).Select(i => i.GetMethod("Foo")); 
    foreach(var method in methods) 
    { 
     var invoked = method.Invoke(b, null); // or add params instead of null when needed 
    } 
+1

謝謝,我忘記了必須明確實現這些實現。 –

+0

請注意,您應該只在'methods'中獲得一個或零個元素,所以'Select'可能需要替換爲更合適的'FirstOrDefault' +檢查。 – SimpleVar

+0

@YoryeNathan你可以獲得多個'MethodInfo'對象。你不能使用FirstOrDefault它擊敗了puropse。 – Blim