检测到在 ASP.NET Core 中调用了 UseStartup<TStartup>

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

配置ASP.NET核心启动时是这样的:

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

我必须在虚拟主机启动后注册一些东西。我可以在位置 (2a) 或辅助程序 UseMyServices() 扩展方法 (2b) 中这样做,这实际上是同一件事。

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

内部 UseServices() 我想进行完整性检查以确保代码放置在正确的位置。我可以使用 hostBuilderContextserviceCollection 来检测 UseStartup<T>() 呼叫已经发出吗?

我在 serviceCollection 中查找了一些有趣的东西,例如IStartup,但没有找到任何有用的东西。可能我不是在找对的东西。

总结: 我如何检测到 UseStartup<TStartup> 调用已经完成?

所有服务都将在 Startup 中调用 Configure 之前注册,无论注册挂钩是在 UseWebHostDefault 之前还是之后。如果这是您的顾虑,那么您无能为力。请注意,将遵守调用 ConfigureServices 的顺序。

我还没有真正找到任何“好的”解决方案,但我确实注意到 ConfigureWebHost(因此 ConfigureWebHostDefaults)的代码将 GenericWebHostService 注册为 IHostedService,也许你可以使用这个。

这里的问题是该服务是 internal 并且它是一个实现细节,因此不能保证在未来的版本中不会是 changed/removed/renamed。无论如何,如果您可以接受这种风险,那么您可以在扩展方法中编写以下代码:

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
        });
}

这里的问题是这并没有具体检测到 UseStartup 被调用,只是 ConfigureWebHostDefaults 是 运行.

--

我发现的另一件事是 UseStartup 将 属性 添加到 HostBuilderContext 属性 (code). Unfortunately the key it uses is a private instance field in an internal class (see here)。即使您想冒着实施更改导致 运行 此处出现时间错误的风险,我也不确定您将如何从此 class.

访问密钥

如果你只是想检查你项目中的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
        });
}