简体   繁体   English

检测到 UseStartup<tstartup> 在 ASP.NET Core 中被调用</tstartup>

[英]Detect that UseStartup<TStartup> was called in ASP.NET Core

When configuring ASP.NET Core startup there's this:配置 ASP.NET 核心启动时有这个:

.ConfigureWebHostDefaults(webHostBuilder => {
  //add services here or in Startup.ConfigureServices()   // (1)
  webHostBuilder.UseStartup<Startup>();
})
.ConfigureServices(serviceCollection => {
  //add services here                                     // (2a)
})
.UseMyServices()                                          // (2b)

I must register something after the web host starts.我必须在 web 主机启动注册一些东西。 I could do so at location (2a) , or in a helper UseMyServices() extension method (2b) , which is effectively the same thing.我可以在位置(2a)或辅助UseMyServices()扩展方法(2b)中执行此操作,这实际上是同一件事。

public static IHostBuilder UseMyServices(this IHostBuilder hostBuilder)
{
  hostBuilder.ConfigureServices((hostBuilderContext, serviceCollection) => {
    //add services here
  };
}

Inside UseServices() I want to do a sanity check to ensure the code was placed at the correct location.UseServices()内部,我想进行健全性检查以确保代码放置在正确的位置。 Can I use hostBuilderContext or serviceCollection to detect that the UseStartup<T>() call was already made?我可以使用hostBuilderContextserviceCollection来检测UseStartup<T>()调用是否已经完成?

I looked in the serviceCollection to find something interesting, eg IStartup , but didn't find anything useful.我查看了serviceCollection以找到一些有趣的东西,例如IStartup ,但没有找到任何有用的东西。 Maybe I'm not looking for the right thing.也许我不是在寻找正确的东西。

Summary: how do I detect that the UseStartup<TStartup> call has been made?摘要:如何检测UseStartup<TStartup>调用已经完成?

All services will be registered before Configure is called in Startup , regardless of whether the hook for registration is before or after UseWebHostDefault .所有服务都将在Startup中调用Configure之前注册,无论注册挂钩是在UseWebHostDefault之前还是之后。 If this is your concern, there's nothing that can be done.如果这是您的顾虑,那么您无能为力。 Note that the order that calls to ConfigureServices are made will be respected.请注意,将遵守调用ConfigureServices的顺序。

I've not really found any "good" solutions, but I did notice that the code for ConfigureWebHost (and therefore ConfigureWebHostDefaults ) registers GenericWebHostService as an IHostedService , so maybe you could use this.我还没有真正找到任何“好的”解决方案,但我确实注意到ConfigureWebHost的代码(因此ConfigureWebHostDefaults )将GenericWebHostService注册为IHostedService ,所以也许你可以使用它。

The issue here is that the service is internal and it's an implementation detail, so there's no guarantee that this won't be changed/removed/renamed in a future version.这里的问题是服务是internal的,它是一个实现细节,所以不能保证它不会在未来的版本中被更改/删除/重命名。 Anyway, if you are OK with that risk, then you could write the following code in your extension method:无论如何,如果您可以接受这种风险,那么您可以在扩展方法中编写以下代码:

public static IHostBuilder UseMyServices(this IHostBuilder hostBuilder)
{
    return hostBuilder
        .ConfigureServices(svc =>
        {
            if (svc.Any(svc => svc.ServiceType == typeof(IHostedService) && svc.ImplementationType.Name == "GenericWebHostService"))
            {
                System.Diagnostics.Debug.WriteLine("After UseWebHostDefault");
            }
            // do your other service registrations
        });
}

The problem here is that this doesn't specifically detect that UseStartup was called, just that ConfigureWebHostDefaults was run.这里的问题是,这并没有专门检测到调用了UseStartup ,只是检测到运行了ConfigureWebHostDefaults

-- --

Another thing I've found is that UseStartup adds a property to the HostBuilderContext properties ( code ).我发现的另一件事是 UseStartup 向HostBuilderContext属性( 代码)添加了一个属性。 Unfortunately the key it uses is a private instance field in an internal class (see here ).不幸的是,它使用的密钥是internal class 中的private实例字段(参见此处)。 Even if you wanted to take the risk of implementation changes causing runtime errors here, I'm not sure how you would access the key from this class.即使您想冒着执行更改导致运行时错误的风险,我也不确定您将如何从这个 class 访问密钥。

If you just want to check if Startup in your project has been called, you could write something like this to check if its instance has been registered:如果你只是想检查你的项目中的Startup是否被调用,你可以写这样的东西来检查它的实例是否已经被注册:

public static IHostBuilder UseMyServices(this IHostBuilder hostBuilder)
{
    return hostBuilder
        .ConfigureServices((ctx, svc) =>
        {
            if (ctx.Properties.Any(p => p.Value?.GetType() == typeof(Startup)))
            {
                System.Diagnostics.Debug.WriteLine("After Startup");
            }
            // do your other service registrations
        });
}

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

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