开发者

How do you refactor two classes with the same, duplicated events?

开发者 https://www.devze.com 2023-04-08 17:01 出处:网络
Both of these classes contain another private class that raises events. These two classes then re-raise these events to clients.

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);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号