自定义Authorization属性注入服务失败,求解决方案
问题根源
属性是在程序启动阶段(编译/初始化时)就被实例化的,而依赖注入(DI)容器是运行时才构建完成的,所以直接在属性中通过静态委托或构造函数注入服务的方式天然存在时机不匹配的问题,这也是你遇到MyService始终为null的核心原因。
正确解决方法
方法1:从请求上下文获取服务(最简单直接)
修改自定义属性,实现IAsyncAuthorizationFilter(避免用async void,防止异常无法捕获),然后在OnAuthorizationAsync方法中通过当前请求的HttpContext获取服务:
public class MyAuthorizationAttribute : Attribute, IAsyncAuthorizationFilter { public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { // 从当前请求的服务容器中获取实例 var myService = context.HttpContext.RequestServices.GetRequiredService<IMyService>(); await myService.Validate(...); Console.WriteLine("OnAuthorization"); } }
使用方式不变,依然可以直接标注[MyAuthorizationAttribute]。
方法2:使用TypeFilter(更符合DI设计)
如果希望过滤器本身通过构造函数注入服务,可以定义独立的过滤器类,再通过TypeFilter特性来使用,TypeFilter会在运行时从DI容器中解析过滤器实例:
- 定义过滤器类:
public class MyAuthorizationFilter : IAsyncAuthorizationFilter { private readonly IMyService _myService; // 构造函数注入服务 public MyAuthorizationFilter(IMyService myService) { _myService = myService; } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { await _myService.Validate(...); Console.WriteLine("OnAuthorization"); } }
- 接口使用时替换为
TypeFilter:
[HttpGet] [TypeFilter(typeof(MyAuthorizationFilter))] [Route(...)] public async Task<ActionResult> GetMyMethodAsync() { //... }
这种方式能让过滤器的生命周期由DI容器管理,避免静态属性带来的生命周期混乱问题。
关于你尝试的静态委托方式(不推荐)
你之前的静态委托失败是因为注册的Func<IMediator>和属性中使用的Func<IMyService>类型不匹配,且未正确初始化静态属性。如果一定要用这种方式,需要:
- 正确注册对应的委托:
builder.Services.AddScoped<IMyService, MyService>(); builder.Services.AddSingleton<Func<IMyService>>(sp => sp.GetRequiredService<IMyService>);
- 在程序启动后初始化静态属性:
var serviceProvider = builder.Build(); MyAuthorizationAttribute.MyService = serviceProvider.GetRequiredService<Func<IMyService>>();
但这种方式会导致Scoped服务被静态引用,引发生命周期错误(比如多个请求共用同一个Scoped实例),因此强烈不推荐。
总结
你原本的使用方式(属性+静态委托)不符合DI的设计逻辑,容易引发问题。推荐使用从请求上下文获取服务或TypeFilter的方式,既满足复用代码的需求,又能正确使用依赖注入。
内容的提问来源于stack exchange,提问作者user7849697
相关产品推荐
相关产品推荐

