ArgumentException OptionsManager 无法转换为服务类型 IOptions

Bru*_*uno 2 c# dependency-injection .net-core

我正在尝试测试是否IServiceCollection可以使用以下代码解决我的所有服务:

static void TestServiceResolve(IServiceCollection services)
{
    var provider = services.BuildServiceProvider();
    foreach (var item in services)
    {
        var serviceToResolve = item.ServiceType;
        var implemantationService = provider.GetService(serviceToResolve);
    }
}
Run Code Online (Sandbox Code Playgroud)

它抛出一个异常:

System.ArgumentException:实现类型“Microsoft.Extensions.Options.OptionsManager`1[TOptions]”无法转换为服务类型“Microsoft.Extensions.Options.IOptions`1[TOptions]”

我已经添加了services.AddOptions();我认为必要的所有可能的软件包。任何人都可以帮助解释这个异常并可能知道它来自哪里吗?

请注意,应用程序代码工作正常,当我调试代码时,所有必需的依赖项都会得到解决,例如IOptions<somesetting>得到很好的解决。只是测试失败了,我不知道它来自哪里。

如果我过滤掉名称以它开头的所有服务,也会IOptions失败ILogger

System.ArgumentException:实现类型“Microsoft.Extensions.Logging.Logger`1[T]”无法转换为服务类型“Microsoft.Extensions.Logging.ILogger`1[TCategoryName]”

同样,日志记录在应用程序中运行良好。

Ste*_*ven 5

服务注册列表包含非泛型(例如HomeController)、封闭泛型(例如ILogger<HomeController>)和开放泛型(例如ILogger<T>)注册,但GetService只能提供非泛型和封闭泛型类型。

换句话说,在迭代列表时,遇到了 of 的注册ServiceTypeILogger<T>但是调用provider.GetService(typeof(ILogger<>))会失败,因为:ILogger<T>你到底想要哪个?请记住,像模板ILogger<T>这样的开放泛型类型,您需要在运行时填充空白(即)才能使其成为“真实”类型。T

我认为问题的根源是 MS.DI 抛出的令人困惑的异常消息。如果它抛出如下所示的异常,那就更好了:

对类型 ILogger<T> 的请求无效,因为它是开放通用类型:只能实例化封闭通用类型的实例。如果泛型类型的所有类型参数都已替换为编译器可识别的类型,则泛型类型将被关闭。

上述消息是直接来自另一个开源 DI 容器的异常。

这里的解决方案是在验证您的 DI 注册时排除所有开放通用注册。例如:

static void TestServiceResolve(IServiceCollection services)
{
    var provider = services.BuildServiceProvider();
    foreach (var item in services)
    {
        if (!item.ServiceType.ContainsGenericParameters)
        {
            provider.GetService(item.ServiceType);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)