C# 调用方需要特定构造函数签名时使用构造函数注入

C# 调用方需要特定构造函数签名时使用构造函数注入,c#,dependency-injection,inversion-of-control,autofac,C#,Dependency Injection,Inversion Of Control,Autofac,我是.NETC#&autofac中DI的新手,在无法完全控制调用方时,我很难理解如何使用DI 有两种情况我很难理解 场景1:调用方需要一个默认构造函数(没有任何参数) 当我在构建类时仍然希望注入一些服务接口时,如何处理这种情况?我在考虑构造函数链接,但这意味着我必须知道具体的类型,它围绕着DI的思想工作。(至少我认为) Scneario 2:调用方需要一个特定的构造函数签名(例如。 这里有同样的问题。当调用方希望构造函数签名完全匹配时,如何注入额外的依赖项 我认为我理解这个概念的主要问题是,当不

我是.NETC#&autofac中DI的新手,在无法完全控制调用方时,我很难理解如何使用DI

有两种情况我很难理解

场景1:调用方需要一个默认构造函数(没有任何参数) 当我在构建类时仍然希望注入一些服务接口时,如何处理这种情况?我在考虑构造函数链接,但这意味着我必须知道具体的类型,它围绕着DI的思想工作。(至少我认为)

Scneario 2:调用方需要一个特定的构造函数签名(例如。 这里有同样的问题。当调用方希望构造函数签名完全匹配时,如何注入额外的依赖项

我认为我理解这个概念的主要问题是,当不是所有的东西都由DI(调用者)构造时,我看不到如何只部分地进行DI


我知道,这是非常基本的,但我相信在继续之前我需要先了解这一点。还有其他选择吗?

正如Steven在评论中正确指出的那样,受限于特定的构造函数签名是受约束构造反模式的一个实例。然而,有时,这可能超出你的理解范围r控制

例如。在这样的示例中,您可能必须遵守第三方框架的规则,因此对此您无能为力。此类框架应该被视为对依赖项注入不友好

考虑OP中的场景2,因为场景1只是场景2的一个特例。如果必须提供具有特定构造函数的类,则可以创建具有所需构造函数签名的类。这使您能够避免使用依赖项注入的精心设计的类受到第三方施加的约束的污染框架。它可以如下所示:

public class ServiceWorker
{
    IService _service;

    public ServiceWorker(string name, string id, IService service) 
    { 
        _service = service
    }
}

public class ServiceWorkerFacade
{
    ServiceWorker imp;

    public ServiceWorkerFacade(string name, string id) 
    { 
        imp =
            new ServiceWorker(
                name,
                id,
                new FooService(
                    new BarService(),
                    new BazService());
    }
}

public class Caller
{
    // No way to change this. 
    var serviceWorker = new ServiceWorkerFacade(name, id);
}
FooService
实现了
IService
。为了让事情变得有趣,我假设
FooService
有自己的依赖项,并且这些依赖项由
BarService
BazService
满足

如史提芬所建议的,那么,可以(从必要性)考虑外观的构造函数./p>


如果您有机会影响相关框架的设计,您可以向开发人员指出。

对于DI,就像async/await一样,“一路向下”是您的朋友。如果您不能修改它,您应该使用合成根目录中的工厂来构造依赖项,或者您应该包装第三方组件。您可以使
ServiceWorker
成为使用“预期”的代理/工厂签名,但在内部创建了
ActualServiceWorker
,它接受注入的依赖项。非常感谢。我想我完全错过了DI的概念…至少我现在感觉很好;-)谢谢大家。拥有一个强制具有特定构造签名的类的概念,称为约束构造。这是一种反模式,但有时在第三方工具强加给您时不可避免。典型的解决方案是使类a中的对象变得尽可能薄,并且只直接从DI容器解析一个服务。这种卑微的东西可以看作是生活的一部分。
public class ServiceWorker
{
    IService _service;

    public ServiceWorker(string name, string id, IService service) 
    { 
        _service = service
    }
}

public class Caller
{
    // No way to change this. 
    var serviceWorker = new ServiceWorker(name, id);
}
public class ServiceWorker
{
    IService _service;

    public ServiceWorker(string name, string id, IService service) 
    { 
        _service = service
    }
}

public class ServiceWorkerFacade
{
    ServiceWorker imp;

    public ServiceWorkerFacade(string name, string id) 
    { 
        imp =
            new ServiceWorker(
                name,
                id,
                new FooService(
                    new BarService(),
                    new BazService());
    }
}

public class Caller
{
    // No way to change this. 
    var serviceWorker = new ServiceWorkerFacade(name, id);
}