c# - 你如何根据用户交替 Ninject 绑定(bind)?

标签 c# asp.net-mvc asp.net-mvc-3 dependency-injection ninject

这个问题需要一些上下文才能理解,所以我将从项目描述开始。

项目背景

我有一个开源项目,它是一个命令提示符样式的网站(U413.comU413.GoogleCode.com)。该项目是在 ASP.NET MVC 3 中构建的,并使用 Entity Framework 4。本质上,该站点允许您传入命令和参数,然后该站点返回一些数据。这个概念相当简单,但我不想使用一个巨大的 IF 语句来处理命令。相反,我决定做一些有点独特的事情,并构建一个包含所有可能命令的对象作为对象的方法。

该站点使用反射来定位与发送的命令对应的方法并执行它们。这个对象是基于当前用户动态构建的,因为一些用户可以访问与其他用户不同的命令(例如,管理员比版主多,管理员比用户多,等等)。

我构建了一个自定义 CommandModuleFactory将在 MVC Controller 中创建并将其称为 BuildCommandModule构建命令模块对象的方法。我现在正在使用 Ninject 进行依赖注入(inject),我想逐步淘汰这个 CommandModuleFactory , 赞成拥有 ICommandModule在 Controller 不做任何工作的情况下注入(inject) Controller 。

ICommandModule定义了一种方法,如下所示:

public interface ICommandModule
{
    object InvokeCommand(string command, List<string> args);
}

InvokeCommand是对自身执行反射以查找可能与传入命令匹配的所有方法的方法。

然后我有五个不同的对象继承自 ICommandModule (其中一些也继承自其他模块,因此我们不重复命令):

AdministratorCommandModule继承自 ModeratorCommandModule继承自 UserCommandModule继承自 BaseCommandModule .

然后我还有VisitorCommandModule继承自 BaseCommandModule因为访问者将无法访问其他三个命令模块中的任何命令。

希望您能开始了解它是如何工作的。到目前为止,我为这一切的运作方式感到非常自豪。

问题

我希望 Ninject 为我构建命令模块并将其绑定(bind)到 ICommandModule这样我就可以让我的 MVC Controller 依赖于 ICommandModule它将收到正确的版本。这是发生绑定(bind)的 Ninject 模块的样子。

public class BuildCommandModule : NinjectModule
{
    private bool _isAuthenticated;
    private User _currentUser;

    public BuildCommandModule(
        bool isAuthenticated,
        string username,
        IUserRepository userRepository
        )
    {
        this._isAuthenticated = isAuthenticated;
        this._currentUser = userRepository.GetUserBy_Username(username);
    }

    public override void Load()
    {
        if (_isAuthenticated)
            if (_currentUser.Administrator)
                //load administrator command module
                this.Bind<ICommandModule>().To<AdministratorCommandModule>();
            else if (_currentUser.Moderator)
                //Load moderator command module
                this.Bind<ICommandModule>().To<ModeratorCommandModule>();
            else
                //Load user command module
                this.Bind<ICommandModule>().To<UserCommandModule>();
        else
            //Load visitor command module
            this.Bind<ICommandModule>().To<VisitorCommandModule>();
    }
}

这里发生了几件事。首先,Ninject 模块依赖于一些东西。它取决于指示用户是否经过身份验证的 bool 值(以确定它是登录命令模块之一还是访问者命令模块)。接下来它取决于字符串用户名和 IUserRepository .这是我在 Global.asax 中定义映射的位置。

    protected override IKernel CreateKernel()
    {
        var kernel = new StandardKernel();

        kernel.Bind<IBoardRepository>().To<BoardRepository>();
        kernel.Bind<IReplyRepository>().To<ReplyRepository>();
        kernel.Bind<ITopicRepository>().To<TopicRepository>();
        kernel.Bind<IUserRepository>().To<UserRepository>();

        kernel.Load(new BuildCommandModule(User.Identity.IsAuthenticated, User.Identity.Name, kernel.Get<IUserRepository>()));

        return kernel;
    }

你可以看到我映射IUserRepository在我加载 Ninject 模块以构建我的命令模块之前转换为它的具体类型(尽量不要将 Ninject 绑定(bind)模块与我的命令模块混淆 :S)。然后我使用 kernel.Get<IUserRepository>()解决我的 Ninject 模块对它的依赖。

我的问题是HttpContext.Current.User一片空白。我不确定如何判断用户是否在 Ninject 绑定(bind)阶段登录。有什么想法吗?

当我进行 Ninject 绑定(bind)时,如何获得对已登录用户的引用?或者你能想出一个更好的方法来为我的 ICommandModule 做条件绑定(bind)吗? ?

最佳答案

您应该使用提供者而不是将逻辑放入您的模块中。首先,您可以创建类似于 SecurityInformation 类的东西,它可以告诉您用户是否经过身份验证以及他们的角色。目前你的实现我认为只使用第一个用户的授权信息来启动应用程序。但是,每次请求此模块的实例时,您都希望检查当前用户的权限。

public class CommandModuleProvider : IProvider
{
    public Type Type { get { return typeof(ICommandModule); } }
    public object Create(IContext context)
    {
        var securityInfo = context.Kernel.Get<SecurityInformation>();
        if (securityInfo.IsAuthenticated)
            if (securityInfo.IsCurrentUserAdministrator)
                //load administrator command module
                return context.Kernel.Get<AdministratorCommandModule>();
            else if (securityInfo.IsCurrentUserModerator)
                //Load moderator command module
                return context.Kernel.Get<ModeratorCommandModule>();
            else
                //Load user command module
                return context.Kernel.Get<UserCommandModule>();
        else
            //Load visitor command module
            return context.Kernel.Get<VisitorCommandModule>();
     }
}   

绑定(bind)将被指定为

Kernel.Bind<ICommandModule>().ToProvider<CommandModuleProvider>();

关于c# - 你如何根据用户交替 Ninject 绑定(bind)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6037549/

相关文章:

c# - 如何在 C# MVC 中创建动态复选框列表组?

entity-framework - 如何使用 Entity Framework Code First 为我的数据库提供种子?

c# - 快速安全的密码算法C#

时间:2019-01-17 标签:c#Windowsforms 'Object reference not set to an instance of an object'

c# - Windows Phone 7 列表框加载数据的进度条

asp.net-mvc - ASP.NET MVC 创建主从关系

javascript - Knockout 是一个慢框架吗?

c# - 将数据上传到 Windows Azure 时收到 409 错误

asp.net-mvc-3 - 在 ASP.NET MVC3 的 Web 网格中使用 List<string> 作为模型

c# - MVC3/C# - 无效的转换异常 - 指定的转换无效