Я использовал Ninject специально в приложении MVC. То, как вы выполняете это с помощью Ninject, заключается в настройке или привязке ваших зависимостей. Когда вы делаете это, вы указываете, как вы хотите управлять временем жизни вашего объекта. В большинстве случаев веб-приложения ваши объекты будут обрабатываться по запросу, как вы указали в своем вопросе.
В вашем вопросе я заметил одну вещь: ваш DomainContext создается объектом IDomainService и используется другими объектами. Если объект службы домена является своего рода фабрикой для DomainContext , то у вас не возникает особых проблем - это становится упражнением в том, как настроить Ninject для предоставления конкретных объектов и внедрения зависимостей.
Вот общие рекомендации о том, как вы будете структурировать свое приложение - имейте в виду, что я не совсем понимаю ваши интерфейсы и классы:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Обратите внимание, что самый простой способ заставить Ninject работать - это извлечь класс приложения из класса NinjectHttpApplication . Вам необходимо изменить RegisterRoutes на метод переопределения, а также потребуется реализовать метод с именем CreateKernel . Метод CreateKernel отвечает за возврат ядра Ninject, которое само является контейнером IoC.
В методе CreateKernel предоставленный Ninject AutoControllerModule сканирует сборки для классов контроллеров MVC и регистрирует их в контейнере. Это означает, что Ninject теперь может вводить зависимости от этих контроллеров, поскольку он стал поставщиком контроллеров для приложения. Класс ServiceModule - это класс, который вам необходимо создать для регистрации всех ваших сервисов в Ninject. Я думаю, это будет выглядеть примерно так:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
У Ninject довольно выразительный интерфейс для настройки. Обратите внимание, что каждый оператор в основном связывает конкретный класс с интерфейсом, который он реализует. Фраза «Использование» в выражении указывает ядру Ninject, что объект будет жить только в течение срока действия запроса. Так, например, это означает, что каждый раз, когда объект IDomainService запрашивается из ядра Ninject во время того же запроса, тот же объект будет возвращен.
Что касается ваших контекстных объектов, то я понимаю, что ваша доменная служба создает эти контексты и действует как своего рода фабрика. В связи с этим я связал экземпляры DomainContext классов выше для получения путем получения значения свойства CurrentDomainContext из IDomainService . Это то, что делает лямбда выше. Приятной особенностью привязки ToMethod в Ninject является то, что у вас есть доступ к объекту контекста активации Ninject, который позволяет разрешать объекты с помощью ядра. Это именно то, что мы делаем, чтобы получить текущий контекст домена.
Следующие шаги должны гарантировать, что ваши объекты принимают зависимости должным образом. Например, вы говорите, что ITrainingService используется только в классе TrainingController . Таким образом, в этом случае я бы гарантировал, что TrainingController имеет конструктор, который принимает параметр ITrainingService . В этом конструкторе вы можете сохранить ссылку на ITrainingService в переменной-члене. Как в:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Помните, что Ninject уже зарегистрировал все ваши контроллеры в ядре Ninject, поэтому, когда этот контроллер будет создан и его действия будут вызваны, вы получите ссылку на ITrainingService в виде trainingService переменная-член.
Надеюсь, это поможет вам. Использование IoC-контейнеров иногда может привести к путанице. Обратите внимание, я настоятельно рекомендую вам ознакомиться с документацией Ninject - это очень хорошо написанное введение в Ninject, а также в концепции DI / IoC. Я также пропустил обсуждение AutoWiringModule, показанного выше; однако, у Нейта Кохари (создателя Ninject) есть хорошая запись в своем блоге об этой функции.
Удачи!