如何使用相同的重复事件重构两个类?

时间:2011-09-24 16:52:57

标签: c# events inheritance

这两个类都包含另一个引发事件的私有类。然后这两个类将这些事件重新提升给客户。

不幸的是,这两个类中的每一个都有完全相同的代码:

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

如您所见,我必须从私有对象重新引发事件。这是多余的。我尝试使用继承并将这些重复的代码放在基类中,但我不断收到如下错误:

  

事件'BaseClass.Foo'只能出现在+ =或 - =的左侧(除非在类型中使用)

有谁知道如何摆脱这些重复的代码?

2 个答案:

答案 0 :(得分:5)

如何将私有对象的事件作为包装器的属性公开?如,

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

如果您熟悉c#属性,则可能已经知道getset个关键字。 add / remove个关键字基本上是相同的,只有当您尝试向您的媒体资源添加或移除某个值时,它们才会被触发。

因此,当您命令(取消)将您的代理注册到ExternalClass.SomeEvent时,您实际上(取消)注册InternalClass.SomeEvent事件。

如果您不熟悉c#属性,http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx会对您有帮助。

答案 1 :(得分:0)

我认为这对你有用。公共接口允许PrivateObject保持内部。唯一的另一个技巧是必须在构造函数中调用RegisterIFooEvents。

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

在控制台应用中运行测试:

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