【问题标题】:Call a parent method before(or after) any child method在任何子方法之前(或之后)调用父方法
【发布时间】:2019-02-19 15:58:56
【问题描述】:

我很可能会在这里得到否定的答案,但我想问我的问题。

在 C# 中是否有一种方法可以在任何子类方法之前(或之后)调用父方法。

public class Base
{
    protected static void ThisWillBeCalledBeforeAnyMethodInChild()
    {
        //do something, e.g. log
    }

    protected static void ThisWillBeCalledAFTERAnyMethodInChild()
    {
        //do something, e.g. log
    }
}

public class SomeClass : Base
{
    public static void SomeMethod1()
    {
        //Do something
    }

    public static void SomeMethod2()
    {
        //Do something
    }
}

所以,我想在 SomeMethod1SomeClass 中的 SomeMethod1SomeMethod2 之前运行基类中的 ThisWillBeCalledBeforeAnyMethodInChild 方法。与 after 方法类似。

有什么方法可以在不使用反射调用方法的情况下做到这一点?

【问题讨论】:

  • 这是您所期望的答案:不。除非在编译时重写代码,或者在运行时生成代理类型(例如方法)。
  • static 很难做到这一点。

标签: c# inheritance


【解决方案1】:

因此,除了在您的子方法调用 base.MethodNameYouWantToCall() 之前或之后,您可以采取不同的方法。

这只是一个想法,可能不是您想要实现的目标,但如果我需要每个子类在某些事情之前和之后调用父函数,我可能会这样做:

class Parent 
{ 
   protected void Before() { /* does things */ }
   protected void After() { /* does things */ }
   abstract void OtherCode();

   public void PubliclyExposedMethod {
        Before();
        OtherCode();
        After();'
}
class Child : Parent {
      OtherCode { Console.Write("Hello world"); }
}

在上面,你在child中定义的方法会ran在before方法之后,在after之前。我认为这更干净,因为它减少了您需要编写 base.() 的次数

【讨论】:

  • 我经常看到这种情况,其中OtherCode() 被称为PubliclyExposedMethodCore() 并且是abstractprotected virtual
  • 这种模式的通用名称是“模板方法”,以防您想进一步阅读它。 en.wikipedia.org/wiki/Template_method_pattern
  • beforeafter 不需要是 protected,只有 OtherCode 需要是 protected。除此之外,很好的答案。
【解决方案2】:

我想到的一个想法是编写一个包装器方法,该方法将操作作为参数。在那里你可以调用你的 before 和 after 方法:

public class SomeClass : Base
{
    public static void SomeMethod1()
    {
        //Do something
    }

    public static void SomeMethod2()
    {
        //Do something
    }

    public static void WrapperMethod(Action action)
    {
        Base.ThisWillBeCalledBeforeAnyMethodInChild();
        action();
        Base.ThisWillBeCalledAFTERAnyMethodInChild
    }

}

你可以这样称呼它:

SomeClass.WrapperMethod(()=> SomeClass.SomeMethod1());

【讨论】:

    【解决方案3】:

    首先,静态方法不参与继承。

    您可以通过使用基指针来完全控制 this,它是对 this 指针的基类的引用。

    class Program
    {
        static void Main(string[] args)
        {
            var s = new SOmeClass();
    
            s.SomeMethod1();
            s.SomeMethod2();
        }
    }
    
    public class Base
    {
        protected  void ThisWillBeCalledBeforeAnyMethodInChild()
        {
            Console.WriteLine("ThisBefore");
        }
    
        protected  void ThisWillBeCalledAFTERAnyMethodInChild()
        {
            Console.WriteLine("ThisAFTER");
        }
    }
    
    public class SOmeClass : Base
    {
        public  void SomeMethod1()
        {
            base.ThisWillBeCalledBeforeAnyMethodInChild();
            Console.WriteLine("SomeMethod1");
        }
    
        public  void SomeMethod2()
        {
            Console.WriteLine("SomeMethod2");
            base.ThisWillBeCalledAFTERAnyMethodInChild();
        }
    }
    

    输出:

    这之前 一些方法1 一些方法2 这之后

    【讨论】:

    • “首先,静态方法不参与继承。”你是如何得出这个结论的?将Base类中的protected改成public,可以看到现在可以访问和调用SomeClass.ThisWillBeCalledBeforeAnyMethodInChild
    • 这不是继承。这只是访问权限。
    • 静态成员被继承,但不能被覆盖。与事件相同。
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    相关资源
    最近更新 更多