Ответ 1
Для решения с одним приложением общим советом является регистрация вашего контейнера в проекте приложения (ваше веб-приложение или проект веб-службы). Для веб-приложения это обычно будет Global.asax Application_Start
. Это место, где вы соединяете все вместе, называется Корень композиции в терминологии DI.
При использовании решения с несколькими приложениями у вас все равно будет один корень композиции для каждого приложения. Это должно быть, поскольку каждое приложение имеет свою уникальную конфигурацию. С другой стороны, дублированный код всегда плох. Вы не хотите менять три места, когда вводите новую абстракцию.
Хитрость заключается в перемещении всех регистраций вниз по иерархии проектов. Например, вы можете определить одну "сборку начальной сборки", которая зависит от ваших сборок бизнес-уровня (и ниже), и пусть у нее будут все регистрации для тех сборок, которые не изменяются. Корни композиций приложений затем могут использовать эту сборку для получения регистраций по умолчанию и расширения ее с зависимыми от приложения зависимостями.
Такая вещь может выглядеть так:
// MVC Composition root
public static void Bootstrap()
{
var container = new Container();
// Default registrations
BusinessLayerBootstrapper.Bootstrap(container);
// Application specific registrations
container.Bind<IUserContext>().To<AspNetUserContext>();
DependencyResolver.Current =
new ContainerDependencyResolver(container);
}
// Windows Service Composition root
public static void Bootstrap()
{
var container = new Container();
// Default registrations
BusinessLayerBootstrapper.Bootstrap(container);
// Application specific registrations
container.Bind<IUserContext>().To<SystemUserContext>()
.SingleScoped();
// Store somewhere.
Bootstrapper.Container = container;
}
// In the BL bootstrap assembly
public static class BusinessLayerBootstrapper
{
public static void Bootstrap(Container container)
{
container.Bind<IDepenency>().To<RealThing>();
// etc
}
}
Хотя вам не нужно иметь отдельную сборку bootstrapper (вы можете поместить этот код в самом BL), это позволит вам не создавать сборки вашего бизнес-уровня без каких-либо зависимостей с вашим контейнером.
Также обратите внимание, что я просто вызываю статический метод Bootstrap()
вместо использования (Ninject) модулей. Я пытался сохранить свой ответ независимо от структуры, так как ваш вопрос является общим, и совет будет одинаковым для всех инфраструктур DI. Однако, конечно, вы можете использовать функцию модуля Ninject, если хотите.