这个问题需要一些上下文才能理解,所以我将从项目描述开始。
项目背景
我有一个开源项目,它是一个命令提示符样式的网站(U413.com、U413.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/