I had an interesting design problem with the class library that I am writing. I have a custom AuthorizeAttribute implementation that I want clients to use like this:
[Protected("permission_name")]
In the above code, PermissionAttribute is inherited from AuthorizeAttribute and uses the local default (DefaultContext created using HttpContext).
Behind the scenes, the attribute uses the SecurityService to check users, roles and permissions (the SecurityService itself uses the client-provided save service, which they can connect to the root directory of their application).
Thus, my attributes need a reference to the SecurityService function. Since attribute constructors can only have compile time constants, I cannot use constructor injection.
I don’t want to force my clients to use the DI structure - they should be able to discover and bind the necessary dependencies at the root of their composition without using the IoC library if they wish.
Here are my options:
- The library uses a singleton SecurityService.
- Use an injection of properties that will work, but
- it makes the addiction seem optional, but it’s not, and
- I do not know where I can inject properties in an MVC application for the authorize attribute.
Possible solution 2. above is to make an instance of SecurityService as a static attribute property at application startup and use the guard clause to prevent it from being set more than once, for example:
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 can be an abstract facade of a service so that it can be extended / replaced by another implementation.
Is there a better way to solve this problem?
UPDATE: adding some code to show how I will do this:
Add a public attribute property that returns the name of the permission:
public class ProtectedAttribute : ... { private string _Permission ; public string Permission { get { return _Permission ; } } public ProtectedAttribute(string permission) { } }
Set the authorization filter and configure the dependency via Ninject (if using Ninject):
using Ninject.Web.Mvc.FilterBindingSyntax; public class MyModule : Ninject.Modules.NinjectModule { public override void Load() {
Oh it's ... beautiful sniffle