简体   繁体   English

Asp.Net Core Dependency Injection ValidateOnBuild 无法正常工作

[英]Asp.Net Core Dependency Injection ValidateOnBuild not works properly

I have a project in .NET 5 with RazorPages, I set this code to validate the Dependecy Injection in the Progam.cs file:我在 .NET 5 中有一个带有 RazorPages 的项目,我设置了这个代码来验证 Progam.cs 文件中的依赖注入:

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseDefaultServiceProvider(options =>
            {
                options.ValidateOnBuild = true;
                options.ValidateScopes = true;
            })....

I forgot to register the service that is injected into my page, so I would have expected that when I try to start the app an error page would show this kind of problem, but I don't understand why it doesn't happen, because for example in case I don't register ILocalizerService this happens: This is my RazorPage:我忘记注册注入到我的页面中的服务,所以我希望当我尝试启动应用程序时,错误页面会显示这种问题,但我不明白为什么它不会发生,因为例如,如果我没有注册 ILocalizerService,就会发生这种情况:这是我的 RazorPage:

public class SignupModel : IdentityPageModel
{
    [BindProperty]
    public Models.Account.Signup Signup { get; set; }

    private readonly CustomUserManager _userManager;
    private readonly ILogger<SignupModel> _logger;
    private readonly INcsService _ncsService;

    public SignupModel(CustomUserManager userManager, 
        ILogger<SignupModel> logger,
        INcsService ncsService) : base(localizerService)
    {
        Guard.Against.Null(userManager, nameof(userManager));

        Guard.Against.Null(logger, nameof(logger));
        Guard.Against.Null(ncsService, nameof(ncsService));
        
        _userManager = userManager;
        _logger = logger;
        _ncsService = ncsService;
    }

    // Other code....
}

This is my service:这是我的服务:

[PublicAPI]
public class NcsService : INcsService
{
    private readonly IHttpClientFactory _httpClientFactory;

    public NcsService(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    // Other code...
}

I have only registered IHttpClientFactory but not INcsService interface and implementation:我只注册了 IHttpClientFactory 但没有注册 INcsService 接口和实现:

services.AddHttpClient(nameof(NcsService), client =>
{
    client.BaseAddress = new Uri(ncsSettings.BaseUri);
    client.DefaultRequestHeaders.Add("x-functions-key", ncsSettings.ApiKey);
    client.DefaultRequestHeaders.Add("x-app-name", "TSID");

}).AddHeaderPropagation(options =>
{
    options.Headers.Add("x-request-id");
    options.Headers.Add("x-correlation-id");
})
.AddPolicyHandler(GetRetryPolicy());

I hope I was clear.我希望我很清楚。
Thank you谢谢

The root of the issue is Microsoft's default IComponentActivator implementation (the DefaultComponentActivator ).问题的根源在于 Microsoft 的默认IComponentActivator实现( DefaultComponentActivator )。 The Component Activator is in control of creating your Razor Pages, but the built-in behavior does not request those pages from the built-in container.组件激活器控制创建 Razor 页面,但内置行为不会从内置容器请求这些页面。 Instead, it just creates them using Activator.CreateInstance .相反,它只是使用 Activator.CreateInstance创建它们。

This means that Blazor does not register your pages in the built-in container and because of that, the page will not be part of the container's verification process.这意味着 Blazor不会在内置容器中注册您的页面,因此,该页面不会成为容器验证过程的一部分。

This is, IMO, a design flaw in Blazor, because it well known, and well understood that, in case you are using a DI Container, you should let all your application components go through the container pipeline.这是,IMO,Blazor 中的一个设计缺陷,因为众所周知,并且很好理解,如果您使用的是 DI 容器,您应该让所有应用程序组件 go 通过容器管道。 That's the only way that the container can give you a reasonable amount of certainty about the validity of your application components.这是容器可以为您提供关于应用程序组件有效性的合理确定性的唯一方法。

Blazor, however, is not the only part of the ASP.NET Core framework where this happens.然而,Blazor 并不是 ASP.NET 核心框架中发生这种情况的唯一部分。 ASP.NET MVC Controllers, for instance, by default aren't registered in the container, and aren't resolved from the container.例如,ASP.NET MVC 控制器默认情况下不会在容器中注册,也不会从容器中解析。 This is configurable though, but since this is not the default behavior, the ValidateOnBuild gives a false sense of security.虽然这是可配置的,但由于这不是默认行为, ValidateOnBuild给人一种错误的安全感。

Other containers might have a more sensible default.其他容器可能有更合理的默认值。 Simple Injector, for instance, (the container that I maintain) contains extension methods that always register all MVC controllers up front.例如,Simple Injector(我维护的容器)包含总是预先注册所有 MVC 控制器的扩展方法。 And with the Blazor integration, similar things happen.而通过 Blazor 集成,也会发生类似的事情

If you stick with the built-in container, it would be good to ensure all components are resolved from the container.如果您坚持使用内置容器,最好确保从容器中解析所有组件。 With MVC this is easy, because you can simply call AddControllersAsServices .使用 MVC 这很容易,因为您可以简单地调用AddControllersAsServices With Blazor, unfortunately, this is much more difficult, because there exists no such method as AddComponentsAsServices .不幸的是,对于 Blazor,这要困难得多,因为不存在AddComponentsAsServices这样的方法。 This means that you have to create a custom IComponentActivator that calls back into the container.这意味着您必须创建一个回调到容器中的自定义IComponentActivator But still, you'll likely have to fallback to the original behavior using Activator.CreateInstance for all Blazor Components that are created by Microsoft, because it might be much harder to find and register them using reflection.但是,您仍然可能不得不对 Microsoft 创建的所有 Blazor 组件使用Activator.CreateInstance回退到原始行为,因为使用反射可能更难找到和注册它们。 For inspiration on how to create such custom Component Activator and register your application Blazor components, take a look at the code presented here .有关如何创建此类自定义组件激活器和注册您的应用程序 Blazor 组件的灵感,请查看此处提供的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM