ASP.NET Core如何不使用弃用的IStartupConfigureServicesFilter实现ConfigureServices前置逻辑
方案1:直接在扩展方法的ConfigureServices回调中注册(适用90%以上常规场景)
ASP.NET Core 中 IWebHostBuilder 配置的所有 ConfigureServices 回调,默认会按照注册顺序依次执行,而 UseStartup<T> 传入的Startup类的 ConfigureServices 方法,执行顺序始终晚于所有通过 builder.ConfigureServices() 显式注册的回调。你直接把需要提前注册的服务写在扩展方法的ConfigureServices里即可,天然就在用户的Startup.ConfigureServices之前执行。
示例代码:
public static IWebHostBuilder ChaseDefaults<TStartup>(this IWebHostBuilder builder) where TStartup : class { builder = builder // 这里的ConfigureServices回调一定会在TStartup的ConfigureServices之前执行 .ConfigureServices((ctx, services) => { // 这里写你要提前注册的服务逻辑 services.AddSingleton<你要提前注册的服务类型>(); // 原来的StartupFilter注册保留 services.AddSingleton<IStartupFilter>(new MyStartupFilter(ctx, services)); }) .UseStartup<TStartup>() .UseSetting(WebHostDefaults.ApplicationKey, ApplicationEnvironment.Name); return builder; }
如果这个方案满足不了你的需求,比如需要严格拦截TStartup的ConfigureServices执行过程、做参数修改等操作,可以用下面的代理Startup方案。
方案2:代理Startup类包装原始启动类
你可以创建一个泛型代理Startup类,在内部持有真实的TStartup实例,先执行你自定义的ConfigureServices逻辑,再调用真实启动类的对应方法,完全控制执行顺序:
第一步:实现代理Startup类
public class ProxyStartup<TRealStartup> where TRealStartup : class { private readonly TRealStartup _realStartup; private readonly WebHostBuilderContext _context; // 构造函数注入和真实Startup一致的参数,框架会自动传入 public ProxyStartup(WebHostBuilderContext context, TRealStartup realStartup) { _context = context; _realStartup = realStartup; } public void ConfigureServices(IServiceCollection services) { // 这里先执行你要提前注册的服务逻辑 // 你的自定义ConfigureServices逻辑写在这里 services.AddSingleton<提前注册的服务类型>(); // 再调用真实Startup的ConfigureServices var configureServicesMethod = typeof(TRealStartup).GetMethod(nameof(ConfigureServices), new[] { typeof(IServiceCollection) }); if (configureServicesMethod != null) { configureServicesMethod.Invoke(_realStartup, new object[] { services }); } } // 透传Configure方法到真实Startup public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { var configureMethod = typeof(TRealStartup).GetMethod(nameof(Configure), new[] { typeof(IApplicationBuilder), typeof(IWebHostEnvironment) }); if (configureMethod != null) { configureMethod.Invoke(_realStartup, new object[] { app, env }); } } }
第二步:修改扩展方法,替换UseStartup的入参
public static IWebHostBuilder ChaseDefaults<TStartup>(this IWebHostBuilder builder) where TStartup : class { builder = builder .ConfigureServices((ctx, services) => services.AddSingleton<IStartupFilter>(new MyStartupFilter(ctx, services))) // 替换为代理Startup .UseStartup<ProxyStartup<TStartup>>() .UseSetting(WebHostDefaults.ApplicationKey, ApplicationEnvironment.Name); return builder; }
这个方案可以完全控制Startup两个核心方法的执行顺序,适配所有复杂场景,不会用到任何已废弃的API,兼容所有ASP.NET Core 2.0+版本。
内容的提问来源于stack exchange,提问作者user17365408
相关产品推荐
相关产品推荐

