2015-12-02 3 views
0

Я хочу использовать контейнер МОК предпочтительно единство в качестве функции распознаватель поискаМОК Контейнер отображения распознаватель

Это то, что я

class ParmaterType {} 

class Monkey : ParmaterType {} 
class Handler {virtual void HandleMessage(){}} 
class MonkeyHandler : Handler {} 

class Main 
{ 
    Dictionary<Type, Type> _Mapper= new> Dictionary<Type, Type >() 
    { { typeof(Monkey) , typeof(MonkeyHandler) } }; 

    public void OnMessage(ParmaterType type) 
    { 
     Handler instance = (Handler)Activator.CreateInstance(_Mapper[type]); 
     instance.HandleMessage(type); 
    } 
} 

и то, что я хочу что-то вроде этого:

IocContainer.Register(typeof(Monkey), typeof(MonkeyHandler)) 

public void OnMessage(ParmaterType type) 
{ 
    ((Handler) (IocContainer.Resolve(type)).HandleMessage(type); 
} 
+3

Вам нужен интерфейс обработчика, может быть один общий и РЕГИСТР обработчики для соответствующих типов обработчиков , Затем, исходя из типа сообщения, вам нужно спросить контейнер для зарегистрированного типа обработчика, который соответствует типу сообщения (таким образом, общий тип обработчика делает его намного проще). Но я с @stuartd, контейнер слишком важен для такой ответственности, подходящая фабрика обработчиков будет лучше здесь. –

+0

Обработчики сообщений разворачиваются в разных местах и ​​постоянно добавляются, я не хочу использовать словарь, потому что, чем каждый новый обработчик, который я добавляю, мне нужно будет перейти в словарь и добавить их, и они уже зарегистрированы в контейнер МОК. поэтому кажется избыточным –

+0

Какой механизм вы используете для динамической регистрации новых обработчиков с помощью контейнера IOC? Я думаю, вы должны быть в состоянии связать это, но трудно сказать, не зная подробности. – StriplingWarrior

ответ

4

Хитрость заключается в том, чтобы сделать общий интерфейс:

public interface IMessageHandler<T> 
{ 
    void Handle(T message); 
} 

public class MonkeyHandler : IMessageHandler<Monkey> 
{ 
    public void Handle(Monkey message) {} 
} 

Чтобы решить обработчик просто сделать:

var monkeyHandler = yourContainer.Resolve<IMessageHandler<Monkey>>(); 

Проблемы в том, что если вы получаете сообщения как object вы не можете сделать переход от объекта к воспроизведенным во время компиляции.

object message = endPoint.Recieve(); 

//not fun to do this: 
if (message is Monkey) 
    container.Resolve<IMessageHandler<Monkey>>((Monkey)message); 

Вместо этого вам необходимо выполнить переход с объектов на типизированные обработчики.

public interface IMessageHandler 
{ 
    void Handle(object message); 
} 
public interface IMessageHandler<T> : IMessageHandler 
{ 
    void Handle(T message); 
} 

public class MonkeyHandler : IMessageHandler<Monkey> 
{ 
    public void Handle(Monkey message) {} 

    //hide from the public API 
    void IMessageHandler.Handle(object message) 
    { 
     Handle((Monkey)message); 
    } 
} 

.. а это значит, что теперь вы можете найти его с помощью Type:

var genericInterfaceType = typeof(IMessageHandler<>).MakeGenericType(message.GetType()); 
var handlerObj = container.Resolve(genericInterfaceType); 

.. так что вы можете бросить его в базовый интерфейс и вызывать его:

var handler = (IMessageHandler)handlerObj; 
handler.Handle(message); 

yay. У нас ЦЕЛЬ!

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

public abstract class HandlerBase<T> : IMessageHandler<T> 
{ 
    public abstract void Handle(Monkey message); 

    void IMessageHandler.Handle(object message) 
    { 
     Handle((T)message); 
    } 
} 

public class MonkeyHandler : HandlerBase<Monkey> 
{ 
    public override void Handle(Monkey message) 
    { 
    } 
} 
Смежные вопросы