В моем приложении MVC3 у меня есть интерфейс IDataRepository, на который ссылаются все мои контроллеры, чтобы дать им доступ к уровню данных.Есть также класс DataRepository, который реализует IDataRepository для определенного источника данных (в моем случае производная среда Entity Framework, полученная из nHydrate).Класс DataRepository принимает один аргумент, который является строкой подключения к базовой базе данных.
Я успешно использовал nInject to для IoC с классами контроллера, используя следующую привязку:
kernel.Bind<IDataRepository>()
.To<DataRepository>()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
Сегодня я прочитал о nInject scoping, и я подумал, что было бы полезно упорядочить вещи так, чтобы для каждого запроса создавался только один экземпляр DatabaseRepository (я думаю, что это будет более эффективно, хотя с EF я не уверен).
К сожалению, я не могу понять, как правильно реализовать шаблон.Например, это не работает:
kernel.Bind<DataRepository>()
.ToSelf()
.InRequestScope()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
kernel.Bind<IDataRepository>()
.To<DataRepository>();
Я думал, что это создаст только один экземпляр DataRepository, который будет использоваться во всех ссылках на IDataRepository.В сообщении об ошибке сообщалось, что не найдено ни одного совпадения для параметра connectionString, а DataRepository не может быть привязан к себе.Я попробовал некоторые варианты, но когда я смог заставить его работать, шаблон синглтона не выполнялся (то есть я мог видеть в отладчике, что создавалось несколько экземпляров DataRepository).
Я пропускаючто-то очевидное здесь:).
--- Приложение --- К сожалению, предложение не препятствует созданию нескольких экземпляров в рамках одного запроса.
Чтобы было понятно, что я пыталсябыл:
public class BaseControllerModule : NinjectModule
{
public override void Load()
{
Bind<IDataRepository>().To<DataRepository>().InRequestScope()
.WithConstructorArgument("connectionString", DataRepositoryBase.GetConnectionString());
}
}
и то, что я наблюдал, было конструктором:
public DataRepository( string connectionString )
: base(connectionString)
{
}
- Дополнительная информация # 2 -
Вот схема классов Ninjectрешает для меня:
public class DataRepositoryBase
{
protected DataRepositoryBase( string connectionString )
{}
public static string GetConnectionString() {}
}
public class DataRepository : DataRepositoryBase, IDataRepository
{
public DataRepository( string connectionString )
: base(connectionString)
{}
}
Я пропустил детали реализации, но, надеюсь, это рисует лучшую картину.
Просматривая это, я думаю, что я вызываю проблемы поделая connectionString параметром конструктора как для DataRepository, так и для его базового класса DataRepositoryBase.Разве Ninject не разрешит connectionString в вызове конструктора базового класса?
ps Я запоздало понял, что мне не нужна DataRepositoryBase, потому что его функциональность можно объединить с DataRepository.Я сделал это, но у меня все еще есть конструктор для DataRepository, вызываемый несколько раз в том, что кажется одним запросом.
p2.s.Ради интереса я попытался объявить InSingletonScope () в определении привязки Ninject.Это сработало - конструктор для DataRepository теперь вызывается только один раз при первом обращении к приложению.Но я не думаю, что это хорошая идея иметь синглтоны в приложении MVC.Похоже, что это приведет к тому, что «состояние» приложения будет «заблокировано» в памяти.
--- но дополнительная информация ---
Проблема, похоже, связана с тем, какЯ разработал свое приложение MVC.Я предполагал, что один запрос от браузера обратно на сервер часто приводит к тому, что несколько запросов обрабатываются последовательно (я наблюдаю за событием BeginRequest, запускаемым в классе MvcApplication).Кажется, что каждый раз, когда я перехожу на другой контроллер, генерируется новый запрос (например, через RedirectToAction).Думаю, это имеет смысл, но это означает, что InRequestScope от Ninject не будет делать то, что я хочу.
Но это также заставляет меня задаться вопросом, неправильно ли я спроектировал приложение.Кажется, мне следует сгруппировать все методы действия, которые могут быть вызваны при вызове браузера, в один контроллер.Вместо этого я организовал методы действий по тому, как они вписываются в концептуальную модель моего приложения.