Этот вопрос требует некоторого контекста, прежде чем он станет понятен, поэтому я просто начну с описания проекта.
История проекта
У меня есть проект с открытым исходным кодом, который представляет собой веб-сайт в стиле командной строки (U413.com, U413.GoogleCode.com). Этот проект построен в ASP.NET MVC 3 и использует Entity Framework 4. По сути, сайт позволяет передавать команды и аргументы, а затем сайт возвращает некоторые данные. Концепция довольно проста, но я не хотел использовать один гигантский оператор IF для обработки команд. Вместо этого я решил сделать что-то несколько уникальное и создать объект, который содержит все возможные команды в качестве методов объекта.
Сайт использует отражение, чтобы найти методы, которые соответствуют отправленной команде, и выполнить их. Этот объект создается динамически на основе текущего пользователя, поскольку некоторые пользователи имеют доступ к командам, отличным от других пользователей (например, администраторы имеют больше модераторов, а моды имеют больше пользователей, и т.д. И т.д.).
Я построил пользовательский CommandModuleFactory
, который будет создан в контроллере MVC, и назову его методом BuildCommandModule
для создания объекта командного модуля. Сейчас я использую Ninject для внедрения зависимостей и хочу постепенно прекратить этот CommandModuleFactory
в пользу введения ICommandModule
в контроллер без выполнения какой-либо работы контроллера.
ICommandModule
имеет один определенный метод, например:
public interface ICommandModule
{
object InvokeCommand(string command, List<string> args);
}
InvokeCommand
- это метод, который выполняет отражение над собой, чтобы найти все методы, которые могут соответствовать переданной команде.
Затем у меня есть пять различных объектов, которые наследуются от ICommandModule
(некоторые из них также наследуются от других модулей, поэтому мы не повторяем команды):
AdministratorCommandModule
наследуется от ModeratorCommandModule
, который наследуется от UserCommandModule
, который наследуется от BaseCommandModule
.
Затем у меня также есть VisitorCommandModule
, который наследуется от BaseCommandModule
, потому что посетители не будут иметь доступа ни к одной из команд в трех других командных модулях.
Надеюсь, вы можете начать видеть, как это работает. Я очень горжусь тем, как все это работает до сих пор.
Вопрос
Я хочу, чтобы Ninject собрал для меня свой командный модуль и связал его с ICommandModule
, чтобы я мог просто сделать свой контроллер MVC зависимым от ICommandModule
, и он получит правильную его версию. Вот как выглядит мой модуль 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 зависит от нескольких вещей. Это зависит от логического значения, указывающего, аутентифицирован ли пользователь или нет (чтобы определить, будет ли он одним из вошедших в систему командных модулей или командным модулем посетителя). Далее это зависит от имени пользователя и строки 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 с моими командными модулями: S). Затем я использую kernel.Get<IUserRepository>()
для разрешения зависимости моего модуля Ninject.
Моя проблема здесь в том, что HttpContext.Current.User
является нулевым. Я не уверен, как определить, вошел ли пользователь в систему на этапе привязки Ninject. Есть идеи?
Как я могу получить ссылку на вошедшего в систему пользователя, когда я делаю привязки Ninject? Или вы можете придумать лучший способ для меня сделать условное связывание для моего ICommandModule
?