【问题标题】:.NET Core fundamentals - Constructor injection behavior.NET Core 基础 - 构造函数注入行为
【发布时间】:2019-07-23 01:11:06
【问题描述】:

我是 .NET 核心的新手,我想使用它开始一个项目。我一直在阅读官方文档和教程。

在微软官方文档中关于依赖注入的“Constructor injection behavior”一节中已经说明“当ActivatorUtilities解析服务时,构造函数注入要求只存在一个适用的构造函数。构造函数重载是支持,但只能存在一个重载,其参数都可以通过依赖注入来实现。"

在那句话中“只有一个适用的构造函数存在”是什么意思?谁能解释一下。如果只有一个,它如何支持构造函数重载。这让我有点困惑。

PS:- 随意投反对票,但如果这个问题不符合标准,请在 cmets 部分提及我应该在哪里问这个问题。

【问题讨论】:

  • 下一句。
  • 我读了整页,花了三个多小时。很抱歉,我仍然无法理解。
  • 换句话说,要使用的构造函数必须是明确的。如果有多个合适的构造函数可以注入所有参数,那么就会出现一些错误。

标签: c# asp.net dependency-injection .net-core


【解决方案1】:

这意味着当你有一个使用 DI 的类时,它必须只有一个构造函数,其中所有参数要么是注册的依赖项(或服务),要么具有默认值。

我注意到文档没有说明如果它确实会发生什么,但我认为它会抛出异常或以某种方式失败(例如,工厂方法返回null?)

文档还指出:

构造函数可以接受依赖注入未提供的参数,但参数必须分配默认值。

举个例子——如果我们有一个 DI 上下文可以提供这些服务:

  • IImageResizerService
  • IImageSavingService
  • IImageObjectRecognizerService

这没关系(单个可满足构造函数):

public class DefaultImageProcessingService : IImageProcessingService
{
    public DefaultImageProcessingService
    (
        IImageResizerService          resizer,
        IImageSavingService           saver,
        IImageObjectRecognizerService recognizer,
        String defaultFileName = null,
        Int32  maxSaveAttempts = 3
    )
    {
        this.resizer    = resizer ?? throw new ArgumentNullException( nameof(resizer) );
        this.saver      = saver   ?? throw new ArgumentNullException( nameof(saver) );
        this.recognizer = recognizer?? throw new ArgumentNullException( nameof(recognizer) );
    }
}
  • 它只有 1 个构造函数
  • 所有构造函数参数都是注册服务或具有默认值。

但这不行(多个可满足的构造函数):

public class DefaultImageProcessingService : IImageProcessingService
{
    public DefaultImageProcessingService
    (
        IImageResizerService resizer,
        String defaultFileName = null,
        Int32 maxSaveAttempts = 3
    )
    {
        this.resizer    = resizer ?? throw new ArgumentNullException( nameof(resizer) );
    }

    public DefaultImageProcessingService
    (
        IImageSavingService saver,
        IImageObjectRecognizerService recognizer,
        String defaultFileName = null,
        Int32 maxSaveAttempts = 3
    )
    {
        this.saver      = saver   ?? throw new ArgumentNullException( nameof(saver) );
        this.recognizer = recognizer?? throw new ArgumentNullException( nameof(recognizer) );
    }
}

这是不可接受的,因为它有两个都将服务注册为参数的构造函数。所以 DI 工厂不知道要使用哪个构造函数,因为它可以使用其中任何一个。

这个例子也是不可接受的(单个不可满足的构造函数):

public class DefaultImageProcessingService : IImageProcessingService
{
    public DefaultImageProcessingService
    (
        IImageResizerService resizer,
        IImageSavingService saver,
        IImageObjectRecognizerService recognizer,
        IMysteryService mystery,
        String defaultFileName = null,
        Int32 maxSaveAttempts = 3
    )
    {
        this.resizer    = resizer ?? throw new ArgumentNullException( nameof(resizer) );
        this.saver      = saver   ?? throw new ArgumentNullException( nameof(saver) );
        this.recognizer = recognizer ?? throw new ArgumentNullException( nameof(recognizer) );
        this.mystery = mystery ?? throw new ArgumentNullException( nameof(mystery) );
    }
}

这是不可接受的,因为IMysteryService 未注册。

这没关系(多个构造函数,但正好1是可以满足的):

public class DefaultImageProcessingService : IImageProcessingService
{
    public DefaultImageProcessingService
    (
        IImageResizerService resizer,
        IImageSavingService saver,
        IImageObjectRecognizerService recognizer,
        String defaultFileName = null,
        Int32 maxSaveAttempts = 3
    )
    {
        this.resizer    = resizer ?? throw new ArgumentNullException( nameof(resizer) );
        this.saver      = saver   ?? throw new ArgumentNullException( nameof(saver) );
        this.recognizer = recognizer?? throw new ArgumentNullException( nameof(recognizer) );
    }

    public DefaultImageProcessingService
    (
        IImageResizerService resizer,
        IImageSavingService saver,
        IImageObjectRecognizerService recognizer,
        IMysteryService mystery,
        String defaultFileName = null,
        Int32 maxSaveAttempts = 3
    )
    {
        this.resizer    = resizer ?? throw new ArgumentNullException( nameof(resizer) );
        this.saver      = saver   ?? throw new ArgumentNullException( nameof(saver) );
        this.recognizer = recognizer ?? throw new ArgumentNullException( nameof(recognizer) );
        this.mystery = mystery ?? throw new ArgumentNullException( nameof(mystery) );
    }
}

这是可以接受的,因为其中一个构造函数只使用注册服务和默认值(第一个构造函数)。 DI 工厂不会使用第二个构造函数,因为它有一个不可满足的参数 (IMysteryService)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2018-11-24
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    相关资源
    最近更新 更多