我在编写的类库中遇到了一个有趣的设计问题。我有一个 AuthorizeAttribute 的自定义实现,我希望客户能够像这样使用它:
[Protected("permission_name")]
在上面的代码中,PermissionAttribute 继承自 AuthorizeAttribute 并使用本地默认值(使用 HttpContext 创建的 DefaultContext)。
在幕后,该属性使用 SecurityService 来检查用户、角色和权限(SecurityService 本身使用客户端提供的持久性服务,他们可以将其连接到其应用程序的组合根中)。
所以我的属性需要引用 SecurityService 才能起作用。由于属性构造函数只能有编译时常量,我不能使用构造函数注入(inject)。
我不想强制我的客户使用 DI 框架 - 他们应该能够发现并连接他们的组合根中的必要依赖关系IoC 库,如果他们愿意的话。
这是我的选择:
- 让图书馆使用单例 SecurityService。
- 使用属性注入(inject),这会起作用但是
- 它会使依赖关系看起来是可选的,但事实并非如此
- 我不知道在 MVC 应用程序中的什么地方可以对授权属性进行属性注入(inject)。
上述 2. 的可能解决方案是在应用程序启动时将 SecurityService 的实例设置为属性的静态属性,并使用保护子句来防止它被设置多次,如下所示:
class ProtectedAttribute : ...
{
private static ISecurityService _SecurityService ;
public static ISecurityService SecurityService
{
get
{
return _SecurityService ;
}
set
{
if (_SecurityService != null)
throw new InvalidOperationException("You can only set the SecurityService once per lifetime of this app.") ;
_SecurityService = value ;
}
}
}
SecurityService 可以是一个抽象的服务门面,这样它就可以被不同的实现扩展/替换。
有没有更好的办法解决这个问题?
更新:添加一些代码来展示我将如何做:
在返回权限名称的属性上添加一个公共(public)属性:
public class ProtectedAttribute : ...
{
private string _Permission ;
public string Permission { get { return _Permission ; } /*...*/ }
public ProtectedAttribute(string permission) { /*...*/ }
}
设置授权过滤器并通过 Ninject 配置依赖项(如果使用 Ninject):
using Ninject.Web.Mvc.FilterBindingSyntax;
public class MyModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
// mySecurityService instance below can have a singleton lifetime - perfect!
this.BindFilter<MyAuthorizationFilter>(FilterScope.Action, 0)
.WhenActionMethodHas<ProtectedAttribute>()
.WithConstructorArgument("securityService", mySecurityService)
.WithConstructorArgumentFromActionAttribute<ProtectedAttribute>("permission", p => p.PermissionName) ;
}
}
哦,这是......美丽的吸 Nose
最佳答案
借助新的 IFilterProvider,您可以在 ASP.NET MVC 3 中使用带有操作过滤器的构造函数注入(inject).这样你就不再需要用 Action 过滤器来装饰你的 Controller Action 了。由于这个界面并使用标记属性,您可以应用它们。
如果您不想手动实现它,您总是可以使用现有的 DI 框架,例如 Ninject,它提供了 fluent way定义操作过滤器依赖项。
关于c# - 将依赖项注入(inject)类库中的 AuthorizeAttribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8760339/