如何重构重复的事件处理代码

时间:2010-11-23 00:06:49

标签: c# inheritance code-duplication

我有以下类允许某些对象订阅更改事件。问题是我还有类B和C,它们需要这个功能,允许对象订阅相同类型的东西。我们当然不希望复制并粘贴此行为。

我们考虑从公共基类继承,但我们所有的类(包括A,B和C)都已经从公共BaseClass继承。我们不希望将此行为添加到BaseClass,因为从BaseClass继承的其他类E,F,G不需要此行为。

有更好的解决方案吗?

public class A : BaseClass
{

    /*other properties and code */

    public event EventHandler OnChange;
    private bool _hasChanged;
    public bool HasChanged
    {
        get { return _hasChanged; }
        set
        {
            _hasChanged = value;
            //only need to notify when we've changed.
            if (value)
            {
                if (OnChange != null)
                    OnChange(this, EventArgs.Empty);
            }
        }
    }
}

4 个答案:

答案 0 :(得分:4)

考虑面向方面的编程方法,就像这个PostSharp example中使用的方法一样。它允许您使用属性注入那种样板代码。

如果您创建了适当的方面,则可以使用以下代码:

public class A : BaseClass
{
    public event EventHandler OnChanged;

    [ChangedNotify("OnChanged")]
    public bool HasChanged { get; set; }
}

或者,如果想要为多个属性设置一个OnChange事件,您可以将其硬编码到方面,将代码减少到

public class A : BaseClass
{
    [NotifyOnChanged]
    public bool HasChanged { get; set; }
}

答案 1 :(得分:2)

如果我们暂时不使用继承怎么办?

1-假设,不是从公共基类继承,而是使用一个实现事件机制的对象来构造需要事件机制的客户端类。

假设我们的班级是

 public class EventNotifier
{
    public event EventHandler OnChange;
    private bool _hasChanged;
    public bool HasChanged
    {
        get { return _hasChanged; }
        set
        {
            _hasChanged = value;
            //only need to notify when we've changed. 
            if (value)
            {
                if (OnChange != null)
                    OnChange(this, EventArgs.Empty);
            }
        }
    }
}

2 -

 public class A
{
    private EventNotifier eventNotifier;
    public EventNotifier MyEventNotifier { get { return eventNotifier; } }

    public A()
    {
        eventNotifier = new EventNotifier();
    }


}

3-现在您的A类用户(继承/组成A类的类)

这适用于B包含A

的情况
 public class b
{
    A obj ;
    public b()
    {
        obj = new A();
        obj.MyEventNotifier.OnChange += new EventHandler(delegate { Console.WriteLine("Hi"); });
        obj. MyEventNotifier.HasChanged = true;
    }
}

答案 2 :(得分:1)

您可以考虑在BaseClass和A,B,C之间引入一个包含常见行为的中间类。这样你就不会污染不需要这种行为的E,F,G。

             BaseClass
  -----------------------------
  |                           |
-----                   NotifyBaseClass
E,F,G                         |
                            -----
                            A,B,C

NB 虽然AOP看起来很好但是我试图让Postsharp与其他技术一起工作时遇到了重大问题,例如MS Code Analysis和MSBuild。

答案 3 :(得分:0)

拥有一个可通知对象的子类可能是要走的路,但它可能很棘手,因为这些方面会成倍增加到各种不同的类中。另一种方法是将它包含在您的基类中并为其定义接口,然后您可以简单地在相关类的接口上添加。

当你跑步时,只需检查它是否是一个IChangeable(或其他东西),然后只与事件挂钩