[英]Custom filter attributes inject dependency
我正在使用 ASP.NET Web API,我需要获得授权,所以我创建了自定义授权属性
public class CustomAuthorizationAttribute : AuthorizeAttribute
为了在构造函数中注入依赖项,我有以下内容:
public CustomAuthorizationAttribute(IAccountBL accountBl)
{
_accountBL = accountBl;
}
在IAccountBL
我有与数据库交互的方法,检查用户是否有权提出请求。 在成员 API 控制器中,我已经注册了该属性
[CustomAuthorization]
public class MemberController : ApiController
但我收到以下错误
Project.Account.AccountBL' 不包含采用 0 个参数的构造函数
如果我注册它像
[CustomAuthorization(IAccountBL)]
谢谢
动作过滤器只是属性。 您无法控制 CLR 何时实例化这些属性。 一种可能性是编写一个标记属性:
public class CustomAuthorizationAttribute : Attribute { }
然后是实际操作过滤器:
public class CustomAuthorizationFilter : ActionFilterAttribute
{
private readonly IAccountBL accountBL;
public CustomAuthorizationFilter(IAccountBL accountBL)
{
this.accountBL = accountBL;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<CustomAuthorizationAttribute>().Any() ||
actionContext.ActionDescriptor.GetCustomAttributes<CustomAuthorizationAttribute>().Any())
{
// here you know that the controller or action is decorated
// with the marker attribute so that you could put your code
}
}
}
最后将其注册为全局操作过滤器:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
IAccountBL accountBL = ...
config.Filters.Add(new CustomAuthorizationFilter(accountBL));
}
}
最后你可以使用标记属性:
[CustomAuthorization]
public class MemberController : ApiController
{
...
}
您可以通过对类HttpRequestMessage
使用扩展方法GetDependencyScope
来获取过滤器中的依赖项。 这不是依赖注入的规范方式,但可以用作解决方法。 一个基本示例可能如下所示:
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var dependencyScope = context.Request.GetDependencyScope();
var dependency = dependencyScope.GetService(typeof (MyDependencyType));
//use your dependency here
}
此方法可与构造函数注入一起使用以简化单元测试:
public class MyAuthenticationFilter : Attribute, IAuthenticationFilter
{
private Func<HttpRequestMessage, MyDependencyType> _dependencyFactory;
public MyAuthenticationFilter() :
this(request => (MyDependencyType)request.GetDependencyScope().GetService(typeof(MyDependencyType)))
{
}
public MyAuthenticationFilter(Func<HttpRequestMessage, MyDependencyType> dependencyFactory)
{
_dependencyFactory = dependencyFactory;
}
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var dependencyScope = context.Request.GetDependencyScope();
var dependency = dependencyFactory.Invoke(context.Request);
//use your dependency here
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public bool AllowMultiple { get; private set; }
}
如果有人发现类似的问题,这就是我设法解决它的方法。
我的自定义过滤器继承IAutofacAuthorizationFilter
。 除了这个,你还可以继承IAutofacExceptionFilter
和IAutofacActionFilter
。 在我的 DI 容器中,我为每个我想像这样使用的控制器注册了这个过滤器
builder.Register(c => new CustomAuthorizationAttribute(c.Resolve<IAccountBL>()))
.AsWebApiAuthorizationFilterFor<MemberController>()
.InstancePerApiRequest();
如果您使用任何容器在应用程序上注册您的服务,则可以很容易地从范围内的任何地方获取您的服务实例。 只需按照以下代码即可获得您的服务。
var myService = DependencyResolver.Current.GetService(typeof(IMyService)) as IMyService;
请确保您已在文件中包含System.Web.Mvc
。
快乐编码!!!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.