Отображение между T -> IHandler <T> - PullRequest
7 голосов
/ 03 апреля 2012

У меня есть следующий интерфейс

public interface IHandler<T>
{
    void Handle(T myObject);
}

Я хотел бы иметь класс HandlersManager с отображением типов объектов в соответствующие им обработчики, но я не уверен, какдолжен определить объект, который содержит это отображение.

Например, что я хотел бы иметь, это:

typeof(string)  --> instance of IHandler<string>
typeof(MyClass) --> instance of IHandler<MyClass>

Лучшее, что я получил до сих пор, было определение Dictionary<Type, object> для отображения, но в этом случае мне придется приводить значение к IHandler<T> каждый раз, когда я его получаю.

Есть ли лучшее решение или что-то, что я полностью пропустил?

Ответы [ 2 ]

10 голосов
/ 03 апреля 2012

Я подозреваю, что вы используете это для разрешения зависимостей.Вместо этого используйте выделенный контейнер, который будет решать эти проблемы для вас.

Если вы не хотите этого делать, вам нужно что-то вроде этого:

Dictionary<Type, object> dictionary;

IHandler<T> Resolve<T>() {
    return (IHandler<T>)dictionary[typeof(T)];
}

Там нет никакогоДругой способ с обобщениями.

Есть ли лучшее решение или что-то, что я полностью пропустил?

Нет, но классы менеджера обычно являются запахами кода.Будьте осторожны.

5 голосов
/ 03 апреля 2012

Это настолько хорошо, насколько это возможно, если использовать только общий интерфейс IHandler<T>.

Чтобы изучить дополнительные параметры, мы можем определить неуниверсальную версию интерфейса:

public interface IHandler
{
    void Handler(object myObject);
}

Тогда вы также можете определить общий абстрактный базовый класс, который реализует IHandler<T> и IHandler:

public abstract class BaseHandler<T> : IHandler, IHandler<T>
{
    public abstract void Handle(T myObject);

    void IHandler.Handle(object myObject)
    {
        ((IHandler<T>)this).Handle((T) myObject);
    }
}

В этот момент у вас может быть IDictionary<Type, IHandler>, и вы можете напрямую вызвать IHandler.Handle для значений, которые вы извлекаете из него:

var obj = /* whatever */
dictionary[obj.GetType()].Handle(obj);

С другой стороны, теперь у нас есть дополнительный интерфейс и абстрактный базовый класс, чтобы скрыть приведение от «пользовательского» кода, что не очень впечатляет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...