【问题标题】:SimpleInjector dictionary as constructor argumentSimpleInjector 字典作为构造函数参数
【发布时间】:2017-02-15 09:07:12
【问题描述】:

我正在尝试设置一个容器来注册一个在其构造函数中接受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 中无法看到的示例。我想避免这样一个事实,即我必须为字典中的每个值实例化一个新接口(..with the relevant parameters...),这就是为什么我认为命名注册在 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 中使用字典方法。

【问题讨论】:

  • 关于键控注册、字典和工厂here 的文档非常丰富。如果本文档没有回答您的问题,请更新您的问题并提供更多详细信息(不要忘记发表评论,以通知任何读者您的问题已更改)。
  • 根据我的实际情况进行了更新。我已经阅读了有关键控注册的信息,但找不到与此特定案例相关的任何内容
  • OtherInterface 如何确定何时使用named-anamed-b?它如何确定密钥ab
  • 在其公共方法调用中作为对象的属性传递
  • 你能发布一些显示这个的代码吗?

标签: c# ioc-container simple-injector


【解决方案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&lt;IInterface&gt;。这样可以即时创建实现,而无需在每次调用时创建所有实现。

您可以按如下方式注册:

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),尽管您的问题提供的上下文数量有限,这有点难以判断。

【讨论】:

  • 我非常喜欢 Func 方法!我会假设所有实例只会在应用程序第一次引导时创建,因为 OtherInterface 会有 LifeStyle.Singleton?
  • @CarlosTorrecillas:在这种情况下,OtherInterface 是否是 Singleton 无关紧要,因为 Func&lt;T&gt; 将在每次调用时将调用转发回容器。这意味着工厂实例的生活方式得以保留,即使 OtherInterfaceSingleton
猜你喜欢
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-17
相关资源
最近更新 更多