У меня возникла интересная проблема дизайна с библиотекой классов, которую я пишу. У меня есть пользовательские реализации AuthorizeAttribute, что я хочу, чтобы клиенты могли использовать так:Включение зависимостей в AuthorizeAttribute в библиотеке классов
[Protected("permission_name")]
В приведенной выше коде, PermissionAttribute наследует от AuthorizeAttribute и использует локальное по умолчанию (DefaultContext создана при HttpContext).
За кулисами атрибут использует SecurityService для проверки пользователей, ролей и разрешений (сам SecurityService использует предоставленную клиентом службу сохранения, которую они могут подключить в корневом каталоге их приложения).
Таким образом, моим атрибутам нужна ссылка на функцию SecurityService. Поскольку конструкторы атрибутов могут иметь только константы времени компиляции, я не могу использовать инъекцию конструктора.
Я не хочу, чтобы заставить своих клиентов использовать рамки DI - они должны быть в состоянии обнаружить и проволоки до необходимых зависимостей в их составе корня без использования библиотеки IoC, если они пожелают.
Вот мои варианты:
- есть библиотека использовать синглтон SecurityService.
- Встраиваться свойство, которое будет работать, но
- это сделает зависимость, кажется, необязательно, что это не так и
- Я не знаю, где я могу сделать инъекции собственности в приложение MVC на атрибуте авторизовать ,
Возможное решение 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 может быть абстрактным фасад службы, так что она может быть расширена/заменена другой реализации.
Есть ли лучший способ решить эту проблему?
UPDATE: Добавление некоторого кода, чтобы показать, как я собираюсь сделать это:
Добавить общественную собственность на атрибут, который возвращает имя разрешения:
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) ;
}
}
Оооо это ... красивый сопеть
Является ли этот ASP.NET MVC 3? –
@ Darin: Да, требуется минимум MVC 3. Обновлены теги. –
Связанные: http://stackoverflow.com/questions/7192543/injecting-dependencies-into-asp-net-mvc-3-action-filters-whats-wrong-with-this/7194467#7194467 –