.NET Core 依赖注入在更新到版本 5.0.0 后出现“不明确的构造函数”错误

问题描述 投票:0回答:1

我有许多使用 API 服务的类,其构造函数遵循以下模式:

public class SomeClass
{
    public SomeClass(IHttpClientFactory factory, ILogger<SomeClass> logger = null)
    {
        // ...
    }
        
    public SomeClass(HttpClient client, ILogger<SomeClass> logger = null)
    {
        // ...
    }
}

第一个构造函数是 .NET Core 内置依赖注入使用的构造函数(通过从

IServicesCollection.AddHttpClient()
方法调用
Startup.ConfigureServices()
,然后在构造函数中调用
IHttpClientFactory.CreateClient()
);第二个构造函数主要用于单元测试,以允许传入
HttpClient
(或模拟)。到目前为止,这一直运行良好,但今天早上我开始收到如下错误:

发生了未处理的异常

系统.InvalidOperationException: 无法激活类型 '服务'。 以下构造函数是不明确的:Void .ctor(System.Net.Http.IHttpClientFactory, Microsoft.Extensions.Logging.ILogger`1[服务])无效 .ctor(System.Net.Http.HttpClient, Microsoft.Extensions.Logging.ILogger`1[服务]) 在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache 生命周期、类型服务类型、类型实现类型、CallSiteChain 呼叫站点链)

...长堆栈跟踪被删除...

到目前为止,这一直有效。当

IHttpClientFactory
HttpClient
不共享任何公共接口时,依赖注入机制认为构造函数是不明确的,这似乎很奇怪。

我周末将 Visual Studio 19 更新到最新版本 (16.8.2) 以及解决方案中的所有 NuGet 包。

Microsoft.Extensions.DependencyInjection
软件包现在版本为 5.0.0;之前版本是 3.1.9。我现在已经解决了这个问题,删除了采用
HttpClient
参数的构造函数,并将测试中的代码替换为使用模拟
IHttpClientFactory
,因此实际影响很小。然而,如果没有别的办法的话,了解一下为什么会出现这种情况,会有助于我内心的平静。我是否忽略了配置 .NET Core 依赖注入的某些方面?或者解决依赖关系的策略在 3.1.9 和 5.0.0 版本之间是否发生了微妙的变化?

.net-core dependency-injection visual-studio-2019
1个回答
1
投票

我在 .net 7 上遇到了这个错误。但是在阅读了有关 .Net 依赖注入的 Microsoft 博客之后,它让我明白了。

对于我的工作来说,我需要使用依赖注入和依赖反转来实例化我的逻辑,或者我们可以将其称为混合。这样我就可以将我的逻辑用于长时间运行的任务和正常的 HttpRequest 线程,而不是单独重复逻辑。

更新

正如Ken Karen在评论中所展示的正确观点是“

The constructor with the most parameters where the types are DI-resolvable is selected
”。

我们必须接受构造函数的两个参数以避免歧义。

    public class SomeClass: ISomeClass
    {
       //constructor that we intend to inject using DI
       //The constructor with the most parameters, going to be selected
       public SomeClass(HttpClient client, IHttpClientFactory factory, ILogger<SomeClass> logger = null)
       {
           // ...
       }
       //construtor that we intend to instantiate using DPI
       public SomeClass(HttpClient client, ILogger<SomeClass> logger = null)
       {
           // ...
       }
    }

OtherClass.cs

   public class OtherClass
   {
      private readonly SomeClass someClass;
      private readonly ISomeClass _someClass;

      //using DI to get "SomeClass" instance
      public OtherClass(ISomeClass iSomeClass)
      {
         _someClass = iSomeClass;
         //dependency inversion (DPI)
         someClass = new SomeClass(httpClient, logger);
      }

   }

也许你的问题已经解决很久了,但我希望这对有类似情况的解决方案查找者有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.