Reputation: 12087
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:
Class A
, B
, and C
Sub Test1()
and Sub Test2()
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
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
Upvotes: 1
Views: 152
Reputation: 12087
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
Upvotes: 0
Reputation: 57217
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
Upvotes: 2