SimpleInjector字典作为构造函数参数

时间:2017-02-15 09:07:13

标签: c# ioc-container simple-injector

我试图设置一个容器来注册一个接受其构造函数为IDictionary<string, IInterface>的类,所以在我的IoC中我想知道如何获取一个命名实例(如果该功能可用)在SI)。我想要实现的一个例子是:

container.Register<IOtherInterface>(() => 
    new OtherInterface(new Dictionary<string, IInterface>
    {
        { "a", container.GetInstance<IInterface>("named-a") },
        { "b", container.GetInstance<IInterface>("named-b") },
    });

有没有办法配置它?

更新:

界面的实现是具有不同参数的同一个对象,这是我在SI文档https://simpleinjector.readthedocs.io/en/latest/howto.html#resolve-instances-by-key中无法看到的一个例子。我想避免这样一个事实:我必须为字典中的每个值实例化一个新的接口(带有相关参数......),这就是为什么我认为命名注册是可用的在SI。

也许我的方法是错误的,我应该尝试以不同的方式建立依赖关系。

使用示例:

public class OtherInterface : IOtherInterface
{
   private readonly IDictionary<string, IInterface> _interfces;

   public OtherInterface(IDictionary<string, IInterface> interfaces)
   {
       _interfaces = interfaces;
   }

   public void DoSomething(MyRequest request)
   {
       if(_interfaces.ContainKey(request.SelectMyInterface))
       {
           _interfaces[request.SelectMyInterface].DoSpecificStuff();
       }
   }
}

我可以扩展接口IInterface并在这里使用类似Applies(string type)的方法应用策略模式,但我在过去使用过Ninject的字典方法。

1 个答案:

答案 0 :(得分:1)

通过手动创建InstanceProducer个实例',在Simple Injector中完成键控注册,如下所示:

var a = Lifestyle.Transient.CreateProducer<IInterface, A>(container);
var b = Lifestyle.Transient.CreateProducer<IInterface, B>(container);

使用这些实例生成器,您可以按如下方式进行字典注册:

container.Register<Dictionary<string, IInterface>(() => new Dictionary<string, IInterface>
{
    { "a", a.GetInstance() },
    { "b", b.GetInstance() },
});

您的OtherInterface看起来像是我的调度员。如果唯一的工作是路由传入的请求,我会说没关系。

但是,我想提出一些不同的设计,而不是注入一个包含已创建实例的完整列表的字典:

public class OtherInterface : IOtherInterface
{
   private readonly IDictionary<string, Func<IInterface>> _interfces;

   public OtherInterface(IDictionary<string, Func<IInterface>> interfaces) {
       _interfaces = interfaces;
   }

   public void DoSomething(MyRequest request) =>
       _interfaces[request.SelectMyInterface].Invoke().DoSpecificStuff();
}

这里的字典包含Func<IInterface>。这样就可以动态创建实现,而无需在每次调用时创建所有实现。

您可以按如下方式注册:

container.RegisterSingleton<IOtherInterface>(new OtherInterface(
    new Dictionary<string, Func<IInterface>>
    {
        { "a", CreateProducer<A>() },
        { "b", CreateProducer<B>() },
    });

private Func<IInterface> CreateProducer<T>() where T : IInterface =>
    Lifestyle.Transient.CreateProducer<IInterface, T>(this.container).GetInstance;

或者,您可能会受益于here所描述的设计(并在here中进行了更详细的解释),尽管您的问题提供的上下文数量有限,但有点难以理解。< / p>