开发者

How to call a member through its parent's type that shadowed a parent class implementation

开发者 https://www.devze.com 2023-03-25 21:33 出处:网络
This is a challenging one that got me stumped while I was coding today. Suppose I am running the Sub Test1() and Test2() and would like to print out the value of the Shadows method of the instance of

This is a challenging one that got me stumped while I was coding today. Suppose I am running the Sub Test1() and Test2() and would like to print out the value of the Shadows method of the instance of the object I am passing in to TestCall() (see below - it is clearer) using the following restrictions:

  1. Can't change the contents of Class A, B, and C
  2. Can't change Sub Test1() and Sub Test2()
  3. TestCall() can't have an if, select case etc. statement that tries to figure out the type of the argument passed in and then do CType(o, <C or B>).Method(). Suppose there are an infinite number of classes like B and C all of which inherit from A or B or C and shadow Method
  4. You can't change the attributes of Subs (i.e. you can't change Shadows to Overridable/Overrides)

I would like to dynamically do the equivalent of CType(o, C).Method() and print out C.Method for Test1 and then dynamically do the equivalent of CType(o, B).Method() and print out 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


You problem comes from the fact that if you use the keyword Shadows you create a new method with the same name that hides the original method, the inverse of overriding an overridable (virtual) method.

The only way that I can think of to solve this dynamically is to find out the declaring type, query that type for existing methods of a certain signature and then call that method.

If this is what you are after, the following code for TestCall (sorry, in C#, but you tagged your question with C#) will do. The only thing you need to know is the name of the method, which you had to know in the original situation also.

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


Another way to do this as I discovered a few days ago WITHOUT reflection:

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号