.net 为什么aspnet服务提供者返回错误结果?

bis0qfac  于 2022-11-19  发布在  .NET
关注(0)|答案(1)|浏览(146)

我有一个关于理解aspnet核心服务提供者问题.我用一个非泛型的具体注册和一个开放的泛型注册来注册一个服务类型,

AddTransient(typeof(IBase<Config>), typeof(Base));
AddTransient(typeof(IBase<>), typeof(BaseGeneric<>));

当我尝试解析所有服务时,行为与我预期的不一样。
我创建了一个空的Web应用程序:

dotnet new web

并更改program.cs,如下所示

ServiceCollection sc = new ServiceCollection();

sc.AddTransient(typeof(IBase<Config>), typeof(Base));
sc.AddTransient(typeof(IBase<>), typeof(BaseGeneric<>));
var serviceProvider = sc.BuildServiceProvider();
var services2 = serviceProvider.GetServices(typeof(IBase<Config>));

foreach (var s in services2){
   Console.WriteLine(s.GetType());
}
Console.WriteLine();
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddTransient(typeof(IBase<Config>), typeof(Base));
builder.Services.AddTransient(typeof(IBase<>), typeof(BaseGeneric<>));

var app = builder.Build();

var services = app.Services.GetServices(typeof(IBase<Config>));

foreach (var s in services){
   Console.WriteLine(s.GetType());
}
app.MapGet("/", () => "Hello World!");

app.Run();

public class Config { }
public interface IBase<T> { }
public class BaseGeneric<T> : IBase<T> { }
public class Base : IBase<Config> { }

两个foreach输出为

Base
BaseGeneric`1[Config]

Base
Base

我希望两个foreach打印相同的结果。但是正如你所看到的,它们返回不同的结果。这是一个有效的假设,他们应该像彼此一样工作吗?如果是的,那么这里的问题是什么?我发现的另一件事是,如果你改变建设者的顺序。服务注册的结果是确定的。

dly7yett

dly7yett1#

这是6.0.0版本的“Microsoft.扩展.依赖性注入”中的一个错误:
https://github.com/dotnet/runtime/issues/65145
当在服务提供者中启用选项ValidateOnBuild时,这会产生一个奇怪的行为来检索通用依赖关系。
计划对.NET 8进行更正。
它通过以下方式进行复制:

>dotnet new console -f net7.0
>dotnet add package Microsoft.Extensions.DependencyInjection --version 6.0.0

通过以下方式修改“Program.cs”:

using Microsoft.Extensions.DependencyInjection;

ServiceCollection sc = new ServiceCollection();

sc.AddTransient(typeof(IBase<Config>), typeof(Base));
sc.AddTransient(typeof(IBase<>), typeof(BaseGeneric<>));

LogServices(sc, false);
LogServices(sc, true);

void LogServices(ServiceCollection sc, bool validate)
{
    Console.WriteLine("ValidateOnBuild: " + validate);
    var serviceProvider = sc.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = validate });
    var services = serviceProvider.GetServices(typeof(IBase<Config>));

    foreach (var s in services)
    {
        Console.WriteLine(s.GetType());
    }
}

public class Config { }
public interface IBase<T> { }
public class BaseGeneric<T> : IBase<T> { }
public class Base : IBase<Config> { }

此错误再现于:

dotnet run
ValidateOnBuild: False
Base
BaseGeneric`1[Config]
ValidateOnBuild: True
Base
Base

如果我们把“Microsoft.Extensions.DependencyInjection”版本降级到先例:

>dotnet add package Microsoft.Extensions.DependencyInjection --version 5.0.2
>dotnet run
ValidateOnBuild: False
Base
BaseGeneric`1[Config]
ValidateOnBuild: True
Base
BaseGeneric`1[Config]

这是预期的行为。
在ASP.NET核心中,当环境是“开发”时,服务生成器是使用选项ValidateOnBuild生成的,并且您具有此行为。在生产中测试,并且您具有预期的行为。

相关问题