传递使用DI同一个接口的多个实现 [英] Passing multiple implementations of the same interface using DI

查看:280
本文介绍了传递使用DI同一个接口的多个实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的一个公司的产品是由许多小的网络,应用程序和窗口服务,又名组件,每一个可能驻留在不同的计算机。其中之一是一个WebForms的项目,作为对所有其他的配置毂

One of our company's products is composed of many small web-applications and a windows service, a.k.a. components, each potentially residing in a different computer. One of them is a WebForms project, which serves as the configuration hub for all the others.

我们正在设计一个功能现在揭露组件的一般信息。想象一下这样一个简单的界面,例如:

We are designing a feature now to expose general information of a component. Imagine a simple interface like this for instance:

public interface IStatistics
{
    Statistics GetStatistics();
}

我们要使用相同的接口上的所有组件,所以这是集中在一个共同的,共享程序集。实施最初将是相同的也,所以它是在这同一个组件中,沿着接口

We want to use this same interface on all components, so this is centralized on a common, shared assembly. The implementation will initially be the same also, so it is in this same assembly, alongside the interface.

当时的想法是揭露一个WCF服务的每个组件,使用上常见的组件都实现和接口。该实现使用环境类返回不同的地方,他们正在运行,就像本地计算机的时间不同的事情。

The idea then is to expose a Wcf service on each component, using both the implementation and interface on the common assembly. The implementation uses environmental classes that return different things depending on where they are running, like local machine time.

我想优雅地解决的问题是如何传递到Web窗体每个组件的所有实现,使用相同的接口。

The problem I would like to solve elegantly is how to pass to the webform all implementations of every component, using the same interface.

我们目前使用团结的,但我想我会面临同样的问题与任何其他DI解。我想注入同样的接口5实现(每个组成部分),并可以通过组件来区分他们(认为词典<成分,I统计量> ,其中组件枚举)。这是必要的,因为将有在页面上下拉选择哪个组件的信息是可见的,并且该网页将再调用正确执行检索的结果。

We currently use Unity, but I suppose I would face the same problem with any other DI solution. I would like to inject 5 implementations of this same interface (one for each component), and be able to differentiate them by component (think a Dictionary<Component, IStatistics>, where Component is an Enum). This is needed because there will be a dropdown on the page to select which component's information is visible, and the page would then call the correct implementation to retrieve the results.

我知道我可以使用命名注册的所有实现,然后注入这些。但是很不幸,这将导致我:

I know I can use named registrations for all implementations and then inject them. Unfortunatelly, this would lead me to:

  1. 有5个不同的参数页面上,每个指向一个组件
  2. 注册在容器上每一个实现使用不同的名称
  3. 在显式注册我的WebForm在容器上,使用自定义InjectionConstructor指定每个注册的接口,以正确的顺序,对页面注入法

我知道团结有ResolveAll方法,从而使人们能获得 I统计量[] 的IEnumerable&LT; I统计量&GT; ,但我无法区分它们。

I know Unity has a ResolveAll method and thus allows one to receive a IStatistics[] or IEnumerable<IStatistics>, but then I won't be able to differentiate them.

我觉得 MEF 与元数据接口的概念,出色的解决了这个。也许会在这个MEF将是一个方式来解决这个问题?我认为这是不恰当的位置,因为这是WCF代理,我们在说什么,我不知道为什么这与MEF在所有集成。

I think MEF solves this brilliantly with the concept of Metadata interfaces. Perhaps going MEF on this would be a way to solve this issue? I think it would be inappropriate here because these are wcf proxies we are talking about, I can't see how this would integrate with MEF at all.

也许使用工厂将是一个更好的策略,但我看不出我将注入服务的工厂也,所以这个问题将持续。

Maybe using a factory would be a better strategy, but I fail to see how I'll inject the services on the factory also, so the problem would persist.

推荐答案

我想知道,你是否能设计出整个事情略有不同。我想你想要做的是有点反对什么的IoC左右。如果我理解正确的话,你需要,你可以以某种方式涉及到不同类型的其他五个对象相同类型的五个实例。 'I统计量'是接口,在一个共同的组件中定义。在实施中,说统计信息在同一个组件。不同类型的五个实例在自己的定义,本地,这是由DI解决,而不是直接引用的程序

I'm wondering, whether you could design the whole thing slightly different. I think what you're trying to do is a bit of against what IoC is about. If I understand you correctly you need five instances of the same type which you can somehow relate to five other objects of different types. 'IStatistics' is the interface, defined in a common assembly. The implementation, say Statistics is in the same assembly. The five instances of different types are defined in their own, 'local', assemblies which are resolved by DI and not directly referenced.

下面是这可能是更直接的想法,并达到你所需要的,而其余的维护和扩展,特别是如果你在某些时候需要不同的实现为每个组件类型:

Here is an idea which might be more straightforward and achieves what you need, while remaining maintainable and extendable, especially if you need different implementations for each component type at some point:

DefaultStatisticsProvider 可以用于组件以实现 IStatisticsProvider 接口。没有DI这里涉及到,因为实现是在公共项目中可用。

DefaultStatisticsProvider can be used by components to implement the IStatisticsProvider interface. There is no DI involved here, because the implementation is available in the common project.

public class DefaultStatisticsProvider : IStatisticsProvider
{
    public Statistics GetStatistics()
    {
        var statistics = new Statistics();
        // Generate statistics data
        return statistics;
     }
} 

该组件实现 IStatisticProvider 直接中继方法类型的私有字段 DefaultStatisticsProvider ,他们在初始化它们构造器:

The components implement IStatisticProvider directly and relay the methods to a private field of type DefaultStatisticsProvider which they initialize in their constructor:

public class ComponentA : IStatisticsProvider
{
    private readonly DefaultStatisticsProvider _statisticsProvider;

    public ComponentA()
    {
        _statisticsProvider = new DefaultStatisticsProvider();
    }

    Statistics IStatisticsProvider.GetStatistics()
    {
        // You could change this implementation later to
        // use a custom statistics provider
        return _statisticsProvider.GetStatistics();
    }
}

现在你可以直接注册组件 IStatisticsProvider 并没有保持某种涉及类型统计数据提供程序实例人工查找表的,因为你的类型的统计机构,哪一种对我来说很有意义的一个合乎逻辑的方式了。类似的信息(伪code):

Now you can register your components as IStatisticsProvider directly and don't have to maintain some kind of artificial lookup table which relates types to statistic provider instances, because your types are statistic providers, which kind of makes sense to me in a logical way, too. Something like (pseudo code):

Container.Register<ComponentA>().As<IStatisticsProvider>();
Container.Register<ComponentB>().As<IStatisticsProvider>();

Container.ResolveAll<IStatisticsProvider>();

会给你

{ Instance of ComponentA, Instance of ComponentB }

另外,如上所述,如果在某一点需要有定制实现,用于提供统计信息,有需要在所有不重新设计。你只是改变了 GetStatistics实施()的组成部分。

这篇关于传递使用DI同一个接口的多个实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆