Как провести рефакторинг двух классов с одинаковыми, дублированными событиями? - PullRequest
6 голосов
/ 24 сентября 2011

Оба этих класса содержат еще один закрытый класс, который вызывает события. Эти два класса затем повторно вызывают эти события для клиентов.

К сожалению, каждый из двух классов имеет такой же код:

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 ]

5 голосов
/ 24 сентября 2011

как насчет того, чтобы выставить события частного объекта как свойства вашей оболочки? Как в,

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 # Properties, вы, вероятно, уже знаете ключевые слова get и set. Ключевые слова add / remove - это одно и то же, только они запускаются, когда вы пытаетесь добавить или удалить значение вашей собственности.

Итак, когда вы приказываете (не) зарегистрировать своего делегата на ExternalClass.SomeEvent, вы фактически (не) регистрируетесь на событие InternalClass.SomeEvent.

Если вы не знакомы с c # Properties, вам поможет http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx.

0 голосов
/ 24 сентября 2011

Я думаю, что это будет работать для вас.Открытый интерфейс позволяет 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...