允许客户端委托覆盖默认行为的模式

时间:2012-06-14 21:53:00

标签: c# delegates

我有一个C#类,它有一些我希望允许该类客户端覆盖的功能。具体来说,我喜欢以下内容:

  1. 如果客户端什么都不做,他们会得到我们的默认行为
  2. 客户端可以覆盖行为并导致我们的默认行为被调用。
  3. 客户端可以覆盖该行为并导致我们的默认行为被称为前/后/中间操作。
  4. 我目前的想法是:

    1. 如果想要覆盖行为,请公开客户端订阅的事件。
    2. 使用默认行为(与事件的签名匹配)公开方法: void DefaultBehavior()
    3. 每当我们尝试触发事件时,如果委托为空,我们调用默认行为方法,否则,我们调用事件的委托:

      if (eventDelegate == null)
          DefaultBehavior();
      else
          eventDelegate();
      
    4. 当客户端覆盖行为时,他们可以选择调用我们的DefaultBehavior方法来获得所需的行为。

      从客户的角度来看,您认为这种方法是否足够直观?或者你能建议任何可能更好的替代方案吗?

4 个答案:

答案 0 :(得分:8)

好吧,如果您希望客户端覆盖某些行为,为什么不创建虚拟功能,让客户端真正override呢?

这是实现这一目标的直接方式。无需重新发明轮子。

答案 1 :(得分:2)

如果我理解你的问题,client你的意思是一些代码打电话给你的班级,而不是覆盖你的班级,假设你需要这样做(我同意@zmbq的答案,如果你能做到这一点方式):

您可以让您的方法有2个重载,一个没有参数,另一个接收Action个对象

public void methodName()
public void methodName(Action delegate)

然后在methodName()的正文中,您将使用defaultAction调用另一个方法

public void methodName()
{
  methodName(DefaultBehavior);
}

最后在第二种方法中,你只需要调用作为参数传递的委托,而不关心它是否是默认值

public void methodName(Action delegate)
{
 delegate();
}

您班级的客户端会看到这两个重载并决定使用默认值还是提供自定义行为

修改 好的,最后一次尝试:),根据您的上一条评论,您可以使用实例字段

private Action behaviorDelegate = DefaultBehavior;

您班级中的任何地方都可以为behaviorDelegate分配不同的行为,然后您不需要if语句,因为行为始终位于delegate变量中,无论是默认与否。这不是一个很大的改变,但对我来说似乎更清洁。

答案 2 :(得分:1)

你可以(也许?)也可以在没有事件的情况下这样做:

<强>声明:

public class DemoClass
{
    public delegate string MyDelegate(string testValue);

    public static MyDelegate DefaultBehavior
    {
        get
        {
            return testValue => 
              { 
                 return String.Concat(testValue, 
                                      ", now with 99% more exclamation points!!!!!!!!"); 
              };
        }
    }

    public MyDelegate ModifyString = testValue => 
        { 
           return DemoClass.DefaultBehavior(testValue); 
        };
}

使用:

// first, default:
DemoClass demoObject = new DemoClass();
Console.WriteLine(demoObject.ModifyString("My test string")); 

// now, pure "override":
demoObject.ModifyString = testVal => 
        { return String.Concat(testVal, ", this time with question marks????"); 
        };
Console.WriteLine(demoObject.ModifyString("Second test string"));

// finally, define a delegate that overrides and calls default:
DemoClass.MyDelegate combined = testVal => 
        { return String.Concat(DemoClass.DefaultBehavior(testVal), 
                               ", now we're really tricky"); 
        };
demoObject.ModifyString = combined;
Console.WriteLine(demoObject.ModifyString("Third test string"));

<强>输出:

My test string, now with 99% more exclamation points!!!!!!!!
Second test string, this time with question marks????
Third test string, now with 99% more exclamation points!!!!!!!!, now we're really tricky

答案 3 :(得分:0)

只需使用虚拟方法:

public class BaseClass {
   public virtual void Something() {
      Console.WriteLine("base functionality");
   }
}

public class Sub1 : BaseClass {
   public override void Something() {
       // do whatever you want here
       base.Something();  // don't call it at all if you like
       // do whatever you want here
   }
}