DI,为一个接口定义注册多个实例

时间:2012-10-14 10:50:59

标签: c# dependency-injection

我有一个接口INavigationService和一个简单的容器,允许使用和不使用密钥进行注册。

这对我很有用,因为框架会将已注册的实例注入我的视图模型的构造函数中。

现在我有多个导航服务(由于我的UI中的帧)。它们都实现了相同的基本界面(INavigationService)。

我希望能够让容器将这些实例注入正确的导航树(框架+后续视图/视图模型),而不必传递参数(DI注册密钥)。

这通常是怎么做的?

我可以想象基于属性的东西(因此将注册密钥放在所有依赖类定义上)。但是容器不支持这个。这似乎也很麻烦。

我还可以创建一个专门用于标记的界面。所以INavigationService<T>并使用不同的类型参数注册每个导航服务。例如。框架的第一个视图的类型。这将给我我需要的解决方案,虽然我会传递没有任何意义的接口。

另一方面,我获得IDE支持以查找依赖视图(例如通过创建类似FileTreeNavigation : INavigationService<FileTreeView>

的类型

还有其他模式吗?

1 个答案:

答案 0 :(得分:1)

我不确定这如何适用于Caliburn Micro,但由于问题是关于模式,我将在这里描述我使用StrucureMap设法解决此问题的方式:使用Ctor<>允许为构造函数参数解析指定具体类型的方法。

另外,我认为使用专门的界面(你的FileTreeNavigation示例)很棒,但如果由于某种原因你没有找到合适的,请继续阅读。

假设我们有INavigationService接口和两个不同的实现:

public interface INavigationService { }
public class NavigationServiceA : INavigationService { }
public class NavigationServiceB : INavigationService { }

接下来,我们有两个不同的Service类,两者都取决于INavigationService接口:

public class ServiceA
{
    private readonly INavigationService _navigationService;

    public ServiceA(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }
}

public class ServiceB
{
    private readonly INavigationService _navigationService;

    public ServiceB(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }
}

最后,我们有一个我们将使用IoC容器解决的类。该课程取决于ServiceAServiceB,定义如下:

public class SomeClassToResolve
{
    private readonly ServiceA _serviceA;
    private readonly ServiceB _serviceB;

    public SomeClassToResolve(ServiceA serviceA, ServiceB serviceB)
    {
        _serviceA = serviceA;
        _serviceB = serviceB;
    }
}

StructureMap提供了指定要使用哪种类型来解析构造函数参数的可能性。这是注册的样子:

ForConcreteType<ServiceA>().Configure.Ctor<INavigationService>().Is<NavigationServiceA>();
ForConcreteType<ServiceB>().Configure.Ctor<INavigationService>().Is<NavigationServiceB>();

现在,当我致电container.GetInstance<SomeClassToResolve>();时,它会构建一个SomeClassToResolve的实例,其中ServiceAServiceB的实例已正确构建(NavigationServiceANavigationServiceB,分别)。

这是一种方法,我发现它更直接。还有可能做Conditional Construction,但我认为这可能会非常复杂。

PS:搜索“caliburn micro constructor”我偶然发现了this approach,这与我在使用StructureMap做的相似(只是在这里它是叫InjectionConstructor)。