【问题标题】:IOC container as mapping resolverIOC 容器作为映射解析器
【发布时间】:2015-12-02 17:22:18
【问题描述】:

我想使用 IOC 容器,最好是统一作为解析器函数查找

这就是我所拥有的

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

【问题讨论】:

  • 您需要一个处理程序接口,可以是一个通用接口,并为它们各自的处理程序类型注册处理程序。然后,根据消息类型,您需要向容器询问与消息类型相对应的已注册处理程序类型(因此通用处理程序类型更容易)。但我和@stuartd 在一起,容器对于这样的责任来说太通用了,这里有一个合适的处理程序工厂会更好。
  • 消息处理程序分散在不同的地方并不断添加,我不想使用字典,因为我添加的每个新处理程序都必须去字典并添加它们,他们已经在 IOC 容器中注册。所以这似乎是多余的
  • 您使用什么机制向您的 IOC 容器动态注册新的处理程序?我认为您应该能够参与其中,但如果不了解更多细节,很难说是如何做到的。
  • 远离 Unity,太可怕了。
  • 工厂方法可以存在于容器中,但它们应该是显式的。即标准的 Resolve 方法不应该根据组件是否注册来实现两种不同的行为。相反,工厂行为应该存在于单独的方法中,以便 dev 可以控制 何时使用或不使用它。解决已注册服务中未注册的依赖关系非常糟糕。生命周期将与服务相同,而不是像对未注册类型进行显式解析那样是瞬态的。

标签: c# unity-container ioc-container


【解决方案1】:

诀窍是使接口通用:

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

耶。我们有一个目标!

要消除在处理程序中从对象转换到类型的重复任务,您可以创建一个基类:

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

【讨论】:

    猜你喜欢
    • 2014-08-07
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    相关资源
    最近更新 更多