Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IoC容器中的命名服务-一个坏主意?_C#_.net_Dependency Injection_Ioc Container_Ninject - Fatal编程技术网

C# IoC容器中的命名服务-一个坏主意?

C# IoC容器中的命名服务-一个坏主意?,c#,.net,dependency-injection,ioc-container,ninject,C#,.net,Dependency Injection,Ioc Container,Ninject,在编写容器时使用服务键(或“命名服务”)似乎不是一个好主意 使用命名服务要求我们要么用匹配的键注释构造函数参数(从而与容器耦合),要么为每个服务执行额外的连接(从而失去容器的大量自动化) 例如,我目前拥有以下接口,该接口由以下类实现: IListSerializer CheckboxListSerializer TreeViewListSerializer 我还有无数的类依赖于其中一个或两个类。但是,AFAIK I应该引用IListSerializer作为我的依赖项,而不是实现。这意味着

在编写容器时使用服务键(或“命名服务”)似乎不是一个好主意

使用命名服务要求我们要么用匹配的键注释构造函数参数(从而与容器耦合),要么为每个服务执行额外的连接(从而失去容器的大量自动化)

例如,我目前拥有以下接口,该接口由以下类实现:

  • IListSerializer
    • CheckboxListSerializer
    • TreeViewListSerializer
我还有无数的类依赖于其中一个或两个类。但是,AFAIK I应该引用
IListSerializer
作为我的依赖项,而不是实现。这意味着我必须使用键/名称来区分它们,这就是它开始变得丑陋的地方

我可以将我的选项视为以下选项之一:

  • 用键注释构造函数参数(依赖项)。与IoC容器耦合
  • 在composition root中执行手动布线。添加重复的膨胀
  • 引用类而不是接口。似乎只是为了满足IoC容器的需要而进行的黑客攻击

有什么建议吗?

一般来说,在为IoC设计组件和服务时,Liskov替代原则是一个非常有用的指南。如果一个服务的两个实现在运行时不能互换使用,那么该服务就太通用了,没有意义。在这个场景中,如果您可以选择的话,我将考虑使用类似于IListSerializer的东西

但是,如果您想使用命名服务,那么使用Autofac进行设置既简单又不具侵入性

首先,用名称注册每个序列化程序:

builder.RegisterType<CheckBoxListSerializer>()
    .Named<IListSerializer>("checkBoxSerializer");
builder.RegisterType<TreeViewListSerializer>()
    .Named<IListSerializer>("treeViewSerializer");

好的容器允许您在不耦合到容器的情况下注释参数。我不理解这种情况:您是说您有一些类特别需要CheckboxListSerializer和一些TreeViewListSerializer?那么,为什么不为每个不同的接口定义一个更具体的接口呢?您希望通过在那个级别上DIing获得什么?@Rup的评论应该是一个答案。定义ICheckboxListSerializer和ITreeViewListSerializer是一个很好的选择。@Martinho-我很想知道如何定义。哪个程序集定义了上述参数属性?如果您回答“Autofac.*”,那么您误判了我所说的耦合。。。实现中不应该有单一的容器技术。Ninject允许您使用自己的属性。当您配置容器时,您只需告诉它哪些属性是这些属性。你提高了我对LSP和Autofac的理解。伟大的引语:“如果一个服务的两个实现在运行时不能互换使用,那么该服务就太通用了,没有意义。”
class NamedParameterResolutionModule<TService> : Module
{
    Parameter _attachedParameter = new ResolvedParameter(
        (pi, c) => pi.ParameterType == typeof(TService),
        (pi, c) => c.ResolveNamed<TService>(pi.Name));

    protected override void AttachToComponentRegistration(
        IComponentRegistry registry,
        IComponentRegistration registration)
    {
        registration.Preparing += (s, e) => {
            e.Parameters = new[] { _attachedParameter }.Contact(e.Parameters);
        };
    }
}
builder.RegisterModule<NamedParameterResolutionModule<IListSerializer>>();
class SomeComponent : ...
{
    public SomeComponent(IListSerializer checkBoxSerializer) { ...
}