简体   繁体   中英

IOC container as mapping resolver

I want to use an IOC container preferably unity as a resolver function lookup

This what I have

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

and what i want is something like this :

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

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

The trick is to make the interface generic:

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

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

To resolve a handler simply do:

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

The problem with that is if you receive messages as object you can't do a transition from object to generics at compile time.

object message = endPoint.Recieve();

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

Instead you need to do a transition from objects to typed handlers.

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

.. which means that you can now locate it using a Type :

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

.. so that you can cast it to the base interface and invoke it:

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

yay. We got a GOAL!

To remove the repetitive task of transitioning from objects to typed in the handlers you could create a base class:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM