2012-10-14 54 views
3

我有一个接口INavigationService和一个允许使用和不使用密钥注册的简单容器。DI,为一个接口定义注册多个实例

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

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

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

这通常如何完成?

我可以想象一些基于属性的东西(因此将注册码放在所有相关的类定义上)。但容器不支持这一点。这似乎也是一个麻烦。

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

在另一方面,我得寻找相关视图IDE的支持(例如,通过像FileTreeNavigation : INavigationService<FileTreeView>

创建类型有另一种格局?

+0

您使用的是什么DI库? – GolfWolf

+0

@ w0lf:容器是Caliburn.Micro的一部分(http://caliburnmicro.codeplex.com/SourceControl/changeset/view/3cc9a20b8554#src%2fCaliburn.Micro.WP71.Extensions%2fSimpleContainer.cs) – skarmats

回答

1

我不知道如何适用于卡利微,但由于问题是关于模式,我将在这里描述我设法用StrucureMap解决这个问题的方法:使用Ctor<>方法,它允许指定具体类型的构造参数分辨率。你的01例如)非常棒,但如果由于某种原因,您认为不合适,请继续阅读。

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

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

接下来,我们有两个不同的服务等级,既取决于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:搜索“卡利微构造”我偶然发现this approach这似乎类似于我与StructureMap(只有在这里,它被称为InjectionConstructor)做的事情。

+0

仅供参考 - 在你的PS中提到的例子是使用不同于内置的DI工具 - 即Microsoft Unity库 – skarmats

+0

感谢您的全面回答。在选择更完整的DI解决方案时,我会考虑使用StructureMap。我在WinRT平台上工作,所以StructureMap不是可行的atm。不过,非常了解这种功能。我认为,我更喜欢接口解决方案,因为我的直接问题是分化来自于依赖关系的真正区别。 INavigationService实际上不可互换,因为它们控制着完全不同的导航空间 - 更好地使接口类型不兼容。但我可以看到你的建议的其他用途。我喜欢。谢谢 – skarmats

+0

@skarmats对不起 - 我没有意识到这一点('InjectionConstructor')。是的,我认为分离界面是最好的方法。 – GolfWolf

相关问题