2011-08-03 4 views
1

これは、私が今日コーディングしている間に私を困惑させた難しいものです。親クラスの実装をシャドーした親の型を通してメンバを呼び出す方法

:次のような制約を使用して - (それが明確である下記参照)私は Sub Test1()Test2()を実行していると私は TestCall()にして渡していたオブジェクトのインスタンス Shadowsメソッドの値をプリントアウトしたいとし
  1. は、Class Aの内容を変更B、及びC
  2. Sub Test1()Sub Test2()
  3. TestCallを(変更できない)ifselect caseらを持つことができないことはできません。 c。引き渡された引数の型を把握しようとする文。次にCType(o, <C or B>).Method()を実行する。 AまたはBまたはCから継承すべてがBCのようなクラスの無限の数があると仮定し、Method
  4. シャドウあなたが潜水艦の属性を変更することはできません(つまり、あなたがOverridable/OverridesShadowsを変更することはできません)

私は動的にCType(o, C).Method()の同等の操作を行うと、Test1のためC.Methodをプリントアウトして、動的に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言語は気にしないでください。私たちが購入したサードパーティのソフトウェアでは、この問題の複雑なバージョンに気付きました。これは、「仮想/上書き」の代わりにほぼすべてのサブについてこの「影」を持っていました(置き換えられない - たくさんの場所を置き換えることができません)それを修正する良い方法を考えていました。 (私のテスト例は本質的に非常に単純なシナリオで問題を捕らえようとしています)リフレクションはいいですし、私はそれについて少し考えましたが、私の最後の手段ですが、私が知らない別のトリックがあるかもしれないと思っていました。 .. – Denis

+0

@Denis:いいえ、他のトリックはありません(異なる反射アプローチ以外)。しかし、他のシナリオのテスト(OP)でこれを使用する必要がある場合は、メソッドをキャッシュすることをお勧めします。ルックアップは非常に高価です。 – Abel

関連する問題