如何通过遮蔽父类实现的父's类型调用成员

本文关键字:类型 成员 调用 何通过 父类 实现 | 更新日期: 2023-09-27 18:04:31

这是一个具有挑战性的问题,当我今天编码时,我被它难住了。假设我正在运行Sub Test1()Test2(),并希望使用以下限制打印出我传递给TestCall()的对象的实例Shadows方法的值(见下面-更清楚):

  1. 不能更改Class ABC的内容
  2. 不能更改Sub Test1()Sub Test2()
  3. TestCall()不能有if, select case等语句,试图找出传入的参数的类型,然后做CType(o, <C or B>).Method()。假设有无限数量的类,如BC,它们都继承自ABC,并影子Method
  4. 你不能改变sub的属性(即你不能将Shadows更改为Overridable/Overrides)

我想动态执行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

如何通过遮蔽父类实现的父's类型调用成员

您的问题来自于这样一个事实:如果您使用关键字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

几天前我发现了另一种方法:

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