How to get rid of this code duplication while still maintaining elegant events?
Ok so let's say I have two classes, class A and class B. They both need to perform a common operation but it wouldn't make sense to have them both derive from the same object so instead we go with composition. Basically, "has a" makes sense where "is a" doesn't.
Now each of the two classes instantiate this object and use it to perform the common operation and all is good. Everything is fine, now.
The problem arises when each of these two classes have to expose an event that the common routine must raise. Uh oh. Now what?
Well, we could do something like this in each of the two classes:
public event EventHandler CommonEvent
{
add { theCommonObject.CommonEvent += value; }
remove { theCommonObject.CommonEvent -= value; }
}
But now this code needs to be duplicated in each of the two classes and readers of the code may be somewhat confused by this code as well. add
and remove
are not very commonly seen keywords, at least.
Still, there is duplicate code in both of the two classes and not only that, but this solution will not always work!
For example, what if theCommonObject
is locally instantiated in a single method and its scope is only within that one method.
Well then, in that case we cannot even use the shortcut code posted earlier and we have to completely duplicate the code in both classes. Not only that but it just screams inelegance because we're basically just re-raising a copy of the event to clients.
Example code that would have to be duplicated in each class in this case:
public event EventHandler SomeCommonEvent;
private void SomeMethod()
{
theCommonObject = new theCommonObject();
theCommonObject.DoSomething();
theCommonObject.SomeCommonEvent += thisClass_SomeCommonEvent;
}
private void thisClass_SomeCommonEvent(object sender, EventArgs e)
{
var handler = SomeCommonEvent;
if (handler != null)
{
handler(this, e);
}
}
As you can see, in both cases there is duplicate code but in the second there is even more because the object is local to a method ra开发者_运维技巧ther than a member variable.
I cannot really think of a way around this, other than using inheritance but I don't think it makes semantic sense to do so, and many often claim that composition is superior to inheritance in terms of complexity-reduction, ease-of-understanding, et cetera.
You say you have a "has-a" relationship. From that, and based on your proposed solution that duplicates code, I assume your class A looks something like:
public class A
{
private SomeCommonObject theCommonObject;
public event EventHandler CommonEvent
{
add { theCommonObject.CommonEvent += value; }
remove { theCommonObject.CommonEvent -= value; }
}
public A()
{
theCommonObject = new SomeCommonObject();
}
}
Where's the problem? theCommonObject
can never be "locally instantiated in a single method and its scope is only within that one method."
Yes, add
and remove
are not commonly used. So what? Clients of the class never see the add
and remove
. They still subscribe to the event using the traditional +=
syntax. The add
and remove
syntax is a non-issue as far as clients are concerned. And you, the developer, who is creating the class, are expected to know about these things.
You could use static helper to get code one time but it's also 'bad'
Problem is implementation can be written one time with derived, you decided not to derive.
精彩评论