AOP: Custom Model Binder Attribute using Ninject
In short: I am trying to create a custom model binder that will take in the type of user and get their id, then use a service class to retrieve the strongly typed object.
If there is a better way to do this, please let me know.
Elabaration:
I have ninject setup with all my bindings within my DomainService layer, 3 web ui's are hooked up to the domain service layer. Each asp.net mvc app loads the bindings into the kernal.
//my custom model binder
public class UserModelBinder : IModelBinder
{
private IAuthenticationService auth;
public UserModelBinder(IAuthenticationService _auth, EntityName type,
string loggedonuserid)
{
this.auth = _auth;
CurrentUserType = type;
CurrentUserId = loggedonuserid;
}
public EntityName CurrentUserType { get; private set; }
private string CurrentUserId { get; set; }
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
object loggedonuser = null;
if (CurrentUserType == EntityName.Client)
loggedonuser = GetLoggedOnClientUser(CurrentUserId);
开发者_如何转开发 else if (CurrentUserType == EntityName.Shop)
loggedonuser = GetLoggedOnShopUser(CurrentUserId);
else
throw new NotImplementedException();
return loggedonuser;
}
public ClientUser GetLoggedOnClientUser(string loggedonuserid)
{
var user = _auth.GetLoggedOnClientUser(loggedonuserid);
if (user == null)
throw new NoAccessException();
return user;
}
public ShopUser GetLoggedOnShopUser(string loggedonuserid)
{
var user = _auth.GetLoggedOnShopUser(loggedonuserid);
if (user == null)
throw new NoAccessException();
return user;
}
}
my Global.aspx.cs
// using NInject to override application started
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
// hand over control to NInject to register all controllers
RegisterRoutes(RouteTable.Routes);
//how do I instantiate?
ModelBinders.Binders.Add(typeof(object), new
UserModelBinder(null,EntityName.Client, User.Identity.Name));
}
My problem is IAuthentication is a service, it is connected to other things like a repository, how do I actually instantiate this properly? Should I create a new NinjectModule? I am really confused with this so any help is greatly appreciated. I have tried to pass in Container.Get(); - but it is null...
NOTE: the reason why I am creating a modelbinder- all controllers will require the type of user as I my service layer requires which type of user is making a request, most methods in my service layer will have overloads where it will do one thing for a ShopUser or ClientUser or any other user in the system...
EDIT: I could very easiy within my controller call upon the IAuthenticationService and get the type of user and pass into my domainservice layer to process the relevant tasks but I just want to know how it is possible with the ModelBindings (and if it makes sense to do it that way).
Edit2: Is there a working sample of using a custom Attribute with AOP with the custom attribute calling/binding/getting an instance of ISomethingService?
You can use the Service Locator pattern here. Pass the Ninject Container (IKernel?) to the constructor and resolve the AuthenticationService each time you need to bind something.
A refinement of this could be to have a constructor argument Func where you pass the function to resolve the service. This would be more explicit and removes the dependency on Ninject. Something like this:
public class MyModelBinder : IModelBinder
{
Func<IAuthenticationService> _resolveAuthService;
public MyModelBinder(Func<IAuthenticationService> resolveAuthService)
{
_resolveAuthService = resolveAuthService;
}
public override object Bind(Context c)
{
var authService = _resolveAuthService();
authService.GetSomething();
// etc...
}
}
精彩评论