在我正在创建的 MVC 项目中,我有以下 RequirePermissionAttribute
,它被用于需要特定权限的任何操作(此示例已对其进行了简化):
public class RequirePermissionAttribute : ActionFilterAttribute, IAuthorizationFilter
{
public Operation Permissions { get; set; }
public RequirePermissionAttribute() { }
public RequirePermissionAttribute(Operation permissions)
{
this.Permissions = permissions;
}
public bool AuthorizeCore(HttpContextBase httpContext)
{
IAuthorizationService authServ = new ASPNETAuthorizationService();
return authServ.Authorize(httpContext);
}
public void OnAuthorization(AuthorizationContext filterContext)
{
Enforce.ArgNotNull(filterContext);
if (this.AuthorizeCore(filterContext.HttpContext))
{
// code snipped.
}
else
{
// code snipped.
}
}
}
所以问题很明显,我的授权属性依赖于我创建的 ASPNETAuthorizationService
。我不能采用构造函数方式,因为属性是编译时检查的。
有一件事要提一下,我正在使用我自己制作的小 IoC,它不支持属性注入(inject)(目前)。当然,如果我确实采用了属性注入(inject)路线,我必须为其添加支持(我必须对此进行一些研究)。
将某些东西注入(inject)属性类的最佳方法是什么?
最佳答案
What's the best way to inject something into an attribute class?
严格来说,我们不能使用依赖注入(inject)来将依赖注入(inject)到属性中。 Attributes are for metadata不是行为。 [AttributeSpecification()]
通过禁止引用类型作为参数来鼓励这一点。
您可能正在寻找的是 use an attribute and a filter together, and then to inject dependencies into the filter .属性添加元数据,元数据决定是否应用过滤器,过滤器接收注入(inject)的依赖。
How to use dependency injection with an attribute?
这样做的理由很少。
也就是说,如果您打算注入(inject)属性,则可以使用 ASP.NET Core MVC IApplicationModelProvider
。框架将依赖项传递给提供者的构造函数,提供者可以将依赖项传递给属性的属性或方法。
在您的 Startup 中,注册您的提供商。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Transient
<IApplicationModelProvider, MyApplicationModelProvider>());
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
在提供者中使用构造函数注入(inject),并将这些依赖项传递给属性。
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
public class MyApplicationModelProvider : IApplicationModelProvider
{
private IUrlHelperFactory _urlHelperFactory;
// constructor injection
public MyApplicationModelProvider(IUrlHelperFactory urlHelperFactory)
{
_urlHelperFactory = urlHelperFactory;
}
public int Order { get { return -1000 + 10; } }
public void OnProvidersExecuted(ApplicationModelProviderContext context)
{
foreach (var controllerModel in context.Result.Controllers)
{
// pass the depencency to controller attibutes
controllerModel.Attributes
.OfType<MyAttribute>().ToList()
.ForEach(a => a.UrlHelperFactory = _urlHelperFactory);
// pass the dependency to action attributes
controllerModel.Actions.SelectMany(a => a.Attributes)
.OfType<MyAttribute>().ToList()
.ForEach(a => a.UrlHelperFactory = _urlHelperFactory);
}
}
public void OnProvidersExecuting(ApplicationModelProviderContext context)
{
// intentionally empty
}
}
使用可以接收依赖项的公共(public) setter 创建一个属性。
using System;
using Microsoft.AspNetCore.Mvc.Routing;
public sealed class MyAttribute : Attribute
{
private string _someParameter;
public IUrlHelperFactory UrlHelperFactory { get; set; }
public MyAttribute(string someParameter)
{
_someParameter = someParameter;
}
}
将属性应用于 Controller 或操作。
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[MyAttribute("SomeArgument")]
public class ValuesController : Controller
{
[HttpGet]
[MyAttribute("AnotherArgument")]
public string Get()
{
return "Foobar";
}
}
上面演示了一种方法,对于罕见的用例,您可以将依赖项注入(inject)属性。如果您找到这样做的正当理由,请将其张贴在评论中。
关于c# - 如何使用属性的依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4102138/