How do you refactor two classes with the same, duplicated events?
Both of these classes contain another private class that raises events. These two classes then re-raise these events to clients.
Unfortunately, each of the two classes has this exact same code:
public class FirstClass
{
public delegate void FooEventHandler(string foo);
public delegate void BarEventHandler(string bar);
public delegate void BazEventHandler(string baz);
public event FooEventHandler Foo;
public event BarEventHandler Bar;
public event BazEventHandler Baz;
private PrivateObject privateObject;
public FirstClass()
{
privateObject.Foo += FirstClass_Foo;
privateObject.Bar += FirstClass_Bar;
privateObject.Baz += FirstClass_Baz;
}
private void FirstClass_Foo(string foo)
{
if (Foo != null)
{
Foo(foo);
}
}
private void FirstClass_Bar(string bar)
{
if (Bar != null)
{
Bar(bar);
}
}
private void FirstClass_Baz(string baz)
{
if (Baz != null)
{
Baz(baz);
}
}
}
As you can see, I have to re-raise events from a private object. It is redundant. I tried using inheritance and placing this duplicate code in a base class but I keep getting errors like:
The event 'BaseClass.Foo' can only appear on the left hand side of += or -= (except when used from within the type)
Does anyo开发者_运维知识库ne know how to get rid of this duplicate code?
what about exposing the events of the private object as properties of your wrapper? As in,
public class ExternalClass
{
private InternalClass _internalObject = new InternalClass();
public event InternalClass.someDelegate SomeEvent
{
add
{
_internalObject.SomeEvent += value;
}
remove
{
_internalObject.SomeEvent -= value;
}
}
}
public class InternalClass
{
public delegate void someDelegate(string input);
public event someDelegate SomeEvent;
}
If you are familiar with c# Properties you probably already know the get
and set
keywords. The add
/remove
keywords are basically the same thing, only they are fired when you attempt to add or remove a value to your property.
So, when you command to (un)register your delegate to ExternalClass.SomeEvent
, you are actually (un)registering to the InternalClass.SomeEvent
event.
If you are not familiar with c# Properties, http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx would help you.
I think this will work for you. The public interface allows PrivateObject to remain internal. The only other trick is that RegisterIFooEvents must be called in the constructor.
public interface IFooEvents
{
event BaseClass.FooEventHandler Foo;
event BaseClass.BarEventHandler Bar;
event BaseClass.BazEventHandler Baz;
}
internal class PrivateObject : IFooEvents
{
public event BaseClass.FooEventHandler Foo;
public event BaseClass.BarEventHandler Bar;
public event BaseClass.BazEventHandler Baz;
public void ChangeFoo(string foo)
{
if (Foo != null)
{
Foo(foo);
}
}
}
public abstract class BaseClass : IFooEvents
{
public delegate void BarEventHandler(string bar);
public delegate void BazEventHandler(string baz);
public delegate void FooEventHandler(string foo);
private IFooEvents _fooEvents;
public event FooEventHandler Foo
{
add { _fooEvents.Foo += value; }
remove { _fooEvents.Foo -= value; }
}
public event BarEventHandler Bar
{
add { _fooEvents.Bar += value; }
remove { _fooEvents.Bar -= value; }
}
public event BazEventHandler Baz
{
add { _fooEvents.Baz += value; }
remove { _fooEvents.Baz -= value; }
}
protected void RegisterIFooEvents(IFooEvents fooEvents)
{
_fooEvents = fooEvents;
}
}
public class FirstClass : BaseClass
{
private readonly PrivateObject _privateObject;
public FirstClass()
{
_privateObject = new PrivateObject();
RegisterIFooEvents(_privateObject);
}
public void ChangeFoo(string foo)
{
_privateObject.ChangeFoo(foo);
}
}
Test run in console app:
class Program
{
static void Main(string[] args)
{
var class1 = new FirstClass();
class1.Foo += EventRaised;
class1.ChangeFoo("TEST");
}
static void EventRaised(string arg)
{
Console.WriteLine(arg);
}
}
精彩评论