Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何根据用户选择Ninject绑定?_C#_Asp.net Mvc_Asp.net Mvc 3_Dependency Injection_Ninject - Fatal编程技术网

C# 如何根据用户选择Ninject绑定?

C# 如何根据用户选择Ninject绑定?,c#,asp.net-mvc,asp.net-mvc-3,dependency-injection,ninject,C#,Asp.net Mvc,Asp.net Mvc 3,Dependency Injection,Ninject,这个问题需要一点背景知识才能理解,所以我将从项目的描述开始 项目背景 我有一个开源项目,它是一个命令提示符风格的网站(,)。该项目是在ASP.NET MVC 3中构建的,并使用实体框架4。基本上,站点允许您传入命令和参数,然后站点返回一些数据。这个概念相当简单,但我不想使用一个巨大的IF语句来处理命令。相反,我决定做一些独特的事情,构建一个对象,其中包含所有可能的命令作为对象上的方法 站点使用反射来定位与发送的命令相对应的方法并执行它们。此对象是基于当前用户动态构建的,因为某些用户可以访问与其他

这个问题需要一点背景知识才能理解,所以我将从项目的描述开始

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

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

我构建了一个自定义的
CommandModuleFactory
,它将在MVC控制器中创建,并将调用它的
BuildCommandModule
方法来构建一个命令模块对象。我现在使用Ninject进行依赖项注入,我想逐步淘汰这个
CommandModuleFactory
,支持在控制器不做任何工作的情况下将
ICommandModule
注入控制器

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

public interface ICommandModule
{
    object InvokeCommand(string command, List<string> args);
}
这里发生了几件事。首先,Ninject模块依赖于一些东西。它取决于一个布尔值,该布尔值指示用户是否经过身份验证(以确定它是登录的命令模块之一,还是访问者命令模块)。接下来,它取决于字符串用户名和
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;
    }
protectedoverride IKernel CreateKernel()
{
var kernel=新的标准内核();
kernel.Bind().To();
kernel.Bind().To();
kernel.Bind().To();
kernel.Bind().To();
Load(新的BuildCommandModule(User.Identity.IsAuthenticated,User.Identity.Name,kernel.Get());
返回内核;
}
您可以看到,在加载Ninject模块以构建命令模块之前,我将
IUserRepository
映射到它的具体类型(尽量不要将Ninject绑定模块与命令模块混淆:S)。然后我使用
kernel.Get()
来解决Ninject模块对它的依赖关系

我这里的问题是
HttpContext.Current.User
为空。我不知道如何判断用户是否在Ninject绑定阶段登录。有什么想法吗


在进行Ninject绑定时,如何获取登录用户的引用?或者,您能为我的
ICommandModule
想出一个更好的方法来进行条件绑定吗?

您应该使用提供程序,而不是将逻辑放入模块中。首先,您可以创建一个类似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>();
     }
}   
公共类CommandModuleProvider:IPProvider
{
公共类型类型{get{return typeof(ICommandModule);}
创建公共对象(IContext上下文)
{
var securityInfo=context.Kernel.Get();
如果(securityInfo.IsAuthenticated)
if(securityInfo.IsCurrentUserAdministrator)
//加载管理员命令模块
返回context.Kernel.Get();
else if(securityInfo.IsCurrentUserModerator)
//加载调节器命令模块
返回context.Kernel.Get();
其他的
//加载用户命令模块
返回context.Kernel.Get();
其他的
//加载访问者命令模块
返回context.Kernel.Get();
}
}   
然后指定绑定,如下所示

Kernel.Bind<ICommandModule>().ToProvider<CommandModuleProvider>();
Kernel.Bind().ToProvider();
应用程序中运行的内核数量应该(非常)有限:大多数情况下最好只有一个。与其尝试为每个用户创建新内核,不如让绑定为每个用户生成不同的实现。正如瓦迪姆指出的那样,这可以使用
i提供程序
s来完成。以下是同一想法的变体:

public override void Load()
{
    Bind<ICommandModule>().ToMethod(
        c =>
            {
                var sessionManager = c.Kernel<ISessionManager>();
                if (!sessionManager.IsAuthenticated)
                    return c.Kernel.Get<VisitorCommandModule>();
                var currentUser = sessionManager.CurrentUser;
                if (currentUser.IsAdministrator)
                    return c.Kernel.Get<AdministratorCommandModule>();
                if (currentUser.IsModerator)
                    return c.Kernel.Get<ModeratorCommandModule>();
                return c.Kernel.Get<UserCommandModule>();
            }).InRequestScope();
}
public override void Load()
{
Bind().ToMethod(
c=>
{
var sessionManager=c.Kernel();
如果(!sessionManager.IsAuthenticated)
返回c.Kernel.Get();
var currentUser=sessionManager.currentUser;
if(currentUser.IsAdministrator)
返回c.Kernel.Get();
if(currentUser.IsModerator)
返回c.Kernel.Get();
返回c.Kernel.Get();
}).InRequestScope();
}
在这个实现中,我希望用一个类来实现
ISessionManager
,该类检查当前的
HttpContext
,以确定谁登录,并提供有关此人的基本信息


InRequestScope()
现在驻留在
Ninject.Web.Common
库中,这将有助于避免每个请求重复执行所有这些逻辑一次以上。

我看到您正在从此提供程序重新调用ICommandModule。我以前没用过。您能给我举个例子说明绑定发生在哪里,以及我将在哪里使用/创建这个IProvider吗?另外,这个SecurityInformation类如何知道用户已登录?为什么这个类是必需的?@Chevex,我已经更新了答案,让你看看绑定。Ninject只会在需要ICommandModule时使用提供程序。Secu
public override void Load()
{
    Bind<ICommandModule>().ToMethod(
        c =>
            {
                var sessionManager = c.Kernel<ISessionManager>();
                if (!sessionManager.IsAuthenticated)
                    return c.Kernel.Get<VisitorCommandModule>();
                var currentUser = sessionManager.CurrentUser;
                if (currentUser.IsAdministrator)
                    return c.Kernel.Get<AdministratorCommandModule>();
                if (currentUser.IsModerator)
                    return c.Kernel.Get<ModeratorCommandModule>();
                return c.Kernel.Get<UserCommandModule>();
            }).InRequestScope();
}