2011-08-03 53 views
1

這是一個具有挑戰性的問題,在我今天編寫代碼的過程中讓我難以置信。假如我是運行Sub Test1()Test2(),想打印出比如我傳遞到TestCall()對象Shadows方法的價值(見下文 - 這是更清晰),使用下列限制:如何通過父類的類型來調用父類的實現

  1. 不能改變的Class AB的內容,和C
  2. 無法變更Sub Test1()Sub Test2()
  3. TESTCALL()不能具有ifselect case等c。聲明試圖找出傳入的參數的類型,然後執行CType(o, <C or B>).Method()。假設有類像BC無限數量的所有這些從ABC繼承和陰影Method
  4. 你不能改變替補的屬性(即你不能改變ShadowsOverridable/Overrides

我願做動態的CType(o, C).Method()相媲美,並打印出C.Method爲Test1的,然後做動態的CType(o, B).Method()相媲美,並打印出B.Method

<TestFixture()> _ 
Public Class Test 

    <Test()> 
    Public Sub Test1() 
     Dim o As A = New C 
     TestCall(o) '<-- THIS SHOULD PRINT "C.Method" 
    End Sub 

    Public Sub Test2() 
     Dim o As A = New B 
     TestCall(o) '<-- THIS SHOULD PRINT "B.Method" 
    End Sub 

    Public Sub TestCall(ByVal o as A) 
      o.Method() 
    End Sub 

    Class A 
     Public Sub Method() 
      Console.WriteLine("A.Method") 
     End Sub 
    End Class 

    Class B 
     Inherits A 

     Public Shadows Sub Method() 
      Console.WriteLine("B.Method") 
     End Sub 
    End Class 

    Class C 
     Inherits B 

     Public Shadows Sub Method() 
      Console.WriteLine("C.Method") 
     End Sub 
    End Class 
End Class 
+0

在本質上你問:如何調用遮蔽方法,就好像它是壓倒一切的方法,正確嗎? – Abel

+0

本質上是的 – Denis

回答

0

另一種方式來做到這一點,因爲我發現前幾天沒有反射:

Public Sub TestCall(ByVal someAorBorC as A) 
    Convert.ChangeType(someAorBorC, someAorBorC.GetType()).Method() 
End Sub 
2

您的問題來自於,如果您使用關鍵字Shadows您創建了一個隱藏原來的方法,覆蓋可克服的(虛擬)方法的逆同名的新方法的事實。

我能想到的動態解決這個問題的唯一方法是找出聲明類型,爲特定簽名的現有方法查詢該類型,然後調用該方法。

如果這就是你所追求的,TestCall的下面的代碼(對不起,在C#中,但你用C#標記了你的問題)將會執行。你唯一需要知道的是方法的名稱,在原始情況下你也必須知道。

public void TestCall(A someAorBorC) 
{ 
    // store declaring type 
    Type T = someAorBorC.GetType(); 

    // find shadowed method 
    var method = (from m in T.GetMethods() 
       where m.DeclaringType == T 
       && m.Name == "Method" 
       select m).SingleOrDefault(); 
    if (method == null) 
     throw new Exception("Method 'Method' not found in declaring type"); 

    // call method 
    method.Invoke(someAorBorC, null); 
} 

// Console: 
C.Method 
B.Method 
+0

不用擔心C#。不關心你喜歡的.NET語言。我們在第三方軟件中注意到了這個問題的一個更復雜的版本,我們購買了幾乎每個子版都有這個「陰影」而不是「虛擬/覆蓋」(無法替代 - 太多地方),我們發現一個bug在它裏面,所以想着解決這個問題的好方法。 (我的測試示例基本上試圖在一個非常簡單的情況下捕捉問題)反射是好的,我簡單地考慮了它,並且將是我的最後手段,但是我想也許還有其他一些我不知道的技巧。 .. – Denis

+0

@Denis:不,沒有其他技巧(除了不同的反射方法)。但是,如果你需要在其他場景的測試(OP)中使用它,那麼我建議你緩存該方法。查找非常昂貴。 – Abel