AOP:使用 Ninject 自定义模型绑定器属性

发布于 2024-10-31 17:10:41 字数 2751 浏览 0 评论 0原文

简而言之:我正在尝试创建一个自定义模型绑定器,它将接受用户类型并获取他们的 ID,然后使用服务类来检索强类型对象。

如果有更好的方法来做到这一点,请告诉我。

详细说明:

我在 DomainService 层中对所有绑定进行了 ninject 设置,3 个 Web ui 连接到域服务层。每个 ASP.NET MVC 应用程序都会将绑定加载到内核中。

//我的自定义模型绑定器

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));

        }

我的问题是 IAuthentication 是一项服务,它连接到其他事物(例如存储库),我如何正确实例化它?我应该创建一个新的 NinjectModule 吗?我真的对此感到困惑,因此非常感谢任何帮助。我尝试传入 Container.Get(); - 但它是空的...

注意:我创建模型绑定器的原因 - 所有控制器都需要用户类型,因为我的服务层需要哪种类型的用户正在发出请求,我的服务层中的大多数方法都会有重载,它将为 ShopUser 或 ClientUser 或系统中的任何其他用户做一件事...

编辑: 我可以在我的控制器中非常轻松地调用 IAuthenticationService 并获取用户类型并传递到我的域服务层来处理相关任务,但我只想知道 ModelBindings 是如何实现的(以及这样做是否有意义)那样)。

Edit2:是否有使用带有 AOP 的自定义属性以及调用/绑定/获取 ISomethingService 实例的自定义属性的工作示例?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烛影斜 2024-11-07 17:10:41

您可以在此处使用服务定位器模式。将 Ninject 容器(IKernel?)传递给构造函数,并在每次需要绑定某些内容时解析 AuthenticationService。

对此的改进可能是有一个构造函数参数 Func,您可以在其中传递函数来解析服务。这会更加明确,并且消除了对 Ninject 的依赖。像这样的东西:

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...
    }
}

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...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文