有没有一种方法可以通过自动调用基本方法来扩展方法,而不用用C#编写调用?

有没有一种方法可以通过自动调用基本方法来扩展方法,而不用用C#编写调用?,c#,polymorphism,overriding,virtual-functions,method-call,C#,Polymorphism,Overriding,Virtual Functions,Method Call,我希望在应该扩展的类中有一个调试记录器。有没有一种方法可以做到这一点,而不必在每个派生类上添加日志条目 using System; public abstract class Phase { public virtual void Start() { Console.Write("[LOG] Start"); } /// <summary> /// Returns true when finished.

我希望在应该扩展的类中有一个调试记录器。有没有一种方法可以做到这一点,而不必在每个派生类上添加日志条目

using System;

public abstract class Phase {
    public virtual void Start() {
        Console.Write("[LOG] Start");
    }

    /// <summary>
    /// Returns true when finished.
    /// </summary>
    public virtual bool Update() {
        Console.Write("[LOG] Update");
        return true;
    }

    public virtual void End() {
        Console.Write("[LOG] End");
    }
}
public class PhaseMenu : Phase {
    private byte _counter;

    public override void Start() {
        _counter = 0;
    }
    
    public override bool Update() {
        _counter++;
        if ( _counter > 100 ) {
            return true;
        }
        return false;
    }

    public override void End() {

    }
}
使用系统;
公共抽象类阶段{
公共虚拟void Start(){
Console.Write(“[LOG]Start”);
}
/// 
///完成时返回true。
/// 
公共虚拟bool更新(){
Console.Write(“[LOG]Update”);
返回true;
}
公共虚拟void End(){
Console.Write(“[LOG]End”);
}
}
公共类阶段:阶段{
专用字节计数器;
公共覆盖无效开始(){
_计数器=0;
}
公共覆盖布尔更新(){
_计数器++;
如果(_计数器>100){
返回true;
}
返回false;
}
公共覆盖无效结束(){
}
}

期望的结果是在调用PhaseMenu的方法时编写日志。因此,这些方法不是重写,而是扩展。

阅读您的问题和相关评论,我能想到的唯一出路是实现某种基于结构的方法。这不仅仅是编写base.Log()的麻烦,但它可能会为您带来好处

基本上你可以订阅每一个方法到一个事件或者类似的事件日志中。这将自动完成

此外,事件订阅可以通过编程方式(通过或其他方式)完成,因此只需几行代码

编辑:
这是一个通过反射解决问题的示例,Dorjan可能也是一个想法:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        var phaseMenu = new PhaseMenu();
        
        phaseMenu.Start();
        phaseMenu.Update();
        phaseMenu.Update();
        phaseMenu.Update();
        phaseMenu.End();
    }
}

public abstract class Phase 
{
    private readonly Action _onStart;
    private readonly Func<bool> _onUpdated;
    private readonly Action _onEnd;

    protected Phase(Action aOnStart, Func<bool> aOnUpdated, Action aOnEnd)
    {
        _onStart = aOnStart;
        _onUpdated = aOnUpdated;
        _onEnd = aOnEnd;
    }
        
    public void Start() 
    {
        Console.WriteLine("[LOG] Start");
        _onStart?.Invoke();
    }
        
    public bool Update() 
    {
        Console.WriteLine("[LOG] Update");
        return _onUpdated?.Invoke() ?? false;
    }

    public void End() 
    {
        Console.WriteLine("[LOG] End");
        _onEnd?.Invoke();
    }
}
    
public class PhaseMenu : Phase 
{
    private static byte _counter;

    public PhaseMenu() : base(OnStart, OnUpdated, OnEnd)
    { }

    private static void OnStart()
    {
        _counter = 0;
    }
    
    private static bool OnUpdated()
    {
        _counter++;
        return _counter > 100;
    }
    
    private static void OnEnd()
    {
        Console.WriteLine("That is all folks!");
    }
}
其思想是,您的基类实现某种契约,让其实现者“遵循”。我给出的一个示例仅限于提供实现的某些方法,但您始终可以提供一个方法来“注册”这些方法的行为

我认为这可以进一步改进,这取决于需要和需要实现的目标,但希望这也能让我了解我的想法

编辑:


我刚刚看到了关于事件的想法,所以这是它的一个简化实现。

不要在基类中将更新方法定义为virtual,然后使用一个新的受保护的虚拟(或抽象)方法,称为PhaseUpdate(),您可以在Update中调用它。从而强制所有调用通过基方法更新

using System;

public abstract class Phase {
    public void Start() {
        Console.Write("[LOG] Start");
        PhaseStart();

    }

    /// <summary>
    /// Returns true when finished.
    /// </summary>
    public bool Update() {
        Console.Write("[LOG] Update");
        return PhaseUpdate();
    }

    public void End() {
        Console.Write("[LOG] End");
        PhaseEnd();
    }

protected void PhaseStart() {
        
    }

    /// <summary>
    /// Returns true when finished.
    /// </summary>
    protected virtual bool PhaseUpdate() {
       
        return true;
    }

    protected virtual void PhaseEnd() {
        
    }

}
public class PhaseMenu : Phase {
    private byte _counter;

    protected override void PhaseStart() {
        _counter = 0;
    }
    
    protected override bool PhaseUpdate() {
        _counter++;
        if ( _counter > 100 ) {
            return true;
        }
        return false;
    }

    protected override void PhaseEnd() {

    }
}

使用系统;
公共抽象类阶段{
公开作废开始(){
Console.Write(“[LOG]Start”);
相位启动();
}
/// 
///完成时返回true。
/// 
公共bool更新(){
Console.Write(“[LOG]Update”);
返回相更新();
}
公共无效结束(){
Console.Write(“[LOG]End”);
相位();
}
受保护的无效PhaseStart(){
}
/// 
///完成时返回true。
/// 
受保护的虚拟布尔相更新(){
返回true;
}
受保护的虚拟空阶段(){
}
}
公共类阶段:阶段{
专用字节计数器;
受保护的覆盖无效PhaseStart(){
_计数器=0;
}
受保护的覆盖布尔相位更新(){
_计数器++;
如果(_计数器>100){
返回true;
}
返回false;
}
受保护的覆盖无效阶段(){
}
}

您是否没有忘记从
PhaseMenu
调用base.Start()?我想知道是否有一种方法可以做到这一点,而不必在每个方法上都编写base.me()?不,我知道。您使用虚拟性,这就是:您需要调用base来传播行为,或者不调用base来破坏行为。我希望这能帮助你享受C#编码:你是说在C#中根本没有办法做到这一点吗?或者如果我用虚拟的?我明白虚拟现实是不可能的,所以我的问题是,是否有更好的方法。如果我不清楚我的任命?好的。很高兴知道。非常感谢。如果你的回答是“不,但是你可以使用Base.MethodName()”,我会标记为正确。事实上,如果事件的使用符合OP的目标,它可能会提供所需的链式处理程序方法池:处理程序执行我想回答,我已经看到了这一点,但需要离开办公桌几个小时。我以前考虑过事件,但我会阅读文章,看看它是否能激发出一个合适的解决方案。谢谢。哦,我明白了,所以我使用反射设置了一个日志类,该类将采用一种类型,并根据触发的事件记录详细信息。你是对的,这可能是过度工程化的,但可能是需要考虑的。@Dorjan是的,我在我的答案中添加了一个链接,这可能有助于理解如何通过思考解决问题。如果有帮助,请将其标记为答案。感谢您提供了它在事件中的外观示例。我会用不同的解决方案玩一玩没问题。祝你好运;)
using System;

public abstract class Phase {
    public void Start() {
        Console.Write("[LOG] Start");
        PhaseStart();

    }

    /// <summary>
    /// Returns true when finished.
    /// </summary>
    public bool Update() {
        Console.Write("[LOG] Update");
        return PhaseUpdate();
    }

    public void End() {
        Console.Write("[LOG] End");
        PhaseEnd();
    }

protected void PhaseStart() {
        
    }

    /// <summary>
    /// Returns true when finished.
    /// </summary>
    protected virtual bool PhaseUpdate() {
       
        return true;
    }

    protected virtual void PhaseEnd() {
        
    }

}
public class PhaseMenu : Phase {
    private byte _counter;

    protected override void PhaseStart() {
        _counter = 0;
    }
    
    protected override bool PhaseUpdate() {
        _counter++;
        if ( _counter > 100 ) {
            return true;
        }
        return false;
    }

    protected override void PhaseEnd() {

    }
}