c# – 当调用者需要特定的构造函数签名时使用构造函数注入

我是.NET C#和DI的新手. autofac并且在我无法完全控制来电方时遇到问题以了解如何使用DI.

我有两个问题需要理解.

场景1:调用者需要一个默认构造函数(没有任何参数)

当我还想在构造类时注入一些服务接口时,如何处理这种情况?我在考虑构造函数链接,但这意味着我必须知道具体的类型,并且它围绕DI的思想工作. (至少我认为).

public class ServiceWorker
{
    IService _service;

    public ServiceWorker(IService service) 
    { 
        _service = service
    }
}

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

Scneario 2:Caller期望一个特定的构造函数签名(例如

同样的问题在这里当调用者期望构造函数签名完全匹配时,如何注入其他依赖项?

我认为我理解这个概念的主要问题是,当不是所有的东西都由DI(来电者)构建时,我不会看到如何仅部分地进行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);
}

我知道,这是非常基本的,但我相信在继续之前我需要首先理解这一点.还有替代品吗?

最佳答案 正如Steven在他的评论中正确指出的那样,仅限于特定的构造函数签名是Constrained Construction反模式的一个实例.但有时,这可能超出您的控制范围.

一个例子是so-called ‘Provider pattern’, which isn’t a pattern at all.在这样的例子中,你可能必须按照第三方框架的规则进行游戏,因此你无能为力.这些框架应被视为对依赖注入不友好.

考虑OP中的场景2,因为场景1只是场景2的特例.如果必须提供具有某个构造函数的类,则可以创建具有所需构造函数签名的Facade.这使您可以避免使用依赖注入的精心设计的类来污染第三方框架强加的约束.它可能看起来像这样:

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满足了这些依赖关系.

正如Steven建议的那样,你可以(从必要性)考虑Facade的构造函数Composition Root.

如果您有任何机会影响相关框架的设计,您可以将开发人员指向my guidance on designing DI-friendly frameworks.

点赞