Question

I have the following class that lets certain objects subscribe to a change event. The problem is that I also have classes B, and C that need this functionality that allow objects to subscribe to the same kind of thing. We certainly don't want to copy and paste this behaviour.

We've considered inheriting from a common base class, but all our classes including A, B, and C already inherit from a common BaseClass. And we don't want to add this behaviour to BaseClass because our other classes E,F,G that inherit from BaseClass don't need this behaviour.

Is there a better solution?

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);
            }
        }
    }
}
Was it helpful?

Solution

What if we don't use inheritance for a moment?

1- Suppose , Instead of inheriting from a common base class, Compose your client class which requires event mechanism with a object which implement event mechanism.

Suppose our class is

 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- Now your users of class A ( class which is inherited / composed class A)

this is for if B contains A

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

OTHER TIPS

Consider an aspect-oriented programming approach, like the one used in this PostSharp example. It would allow you to inject that kind of boilerplate code using attributes.

If you created the appropriate aspect, you could then have code like:

public class A : BaseClass
{
    public event EventHandler OnChanged;

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

or, if the idea is to have a single OnChange event for multiple properties, you could just hard-code that into the aspect, reducing your code to

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

You could consider introducing an intermediary class between BaseClass and A,B,C that contains the common behaviour. In this way you will not be polluting E,F,G which do not need the behaviour.

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

NB Although AOP looks yummy I have had major problems trying to get Postsharp to work with other technologies e.g. MS Code Analysis and MSBuild.

Having a subclass for notifyable objects might be the way to go but it can be tricky with aspects multiplying that way into a wide range of different classes. Another way would to infact include it in your base class and define an interface for it, then you can simply tack on the interface for the relevant classes.

When running yous simply check if it's a IChangeable (or something) and only hook up to the event then

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top