Подтвердить что ты не робот

Использование Nininject MVC с библиотеками классов

Я совершенно новичок в рамках IoC, поэтому, пожалуйста, извините за терминологию.

Итак, у меня есть проект MVC с ссылками Nininject MVC. У меня есть другие классы в моем проекте, например. Уровень домена, я хотел бы иметь возможность использовать инфраструктуру Ninject, но все мои привязки находятся в NinjectWebCommon.cs в папке App_Start в проекте MVC:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IHardwareService>().To<WindowsHardwareService>();
    kernel.Bind<IStatusApi>().To<StatusApiController>();
}

В настоящее время в моей библиотеке классов я использую инъекцию конструктора, но иногда мне приходится жестко кодировать зависимости:

var service = new WindowsHardwareService();

Когда я хотел бы иметь возможность сделать следующее:

IKernel kernel = new StandardKernel(.....);
var context = kernel.Get<IHardwareService>();

Я не делал следующее, потому что у меня нет модулей? Вся документация, которую я прочитал, в основном направлена ​​на обычную библиотеку Ninject, а не на версию MVC.

Что мне нужно делать, и как я могу использовать обычную библиотеку Ninject с версией MVC?

Обновление

Вот что я пробовал:

Цель этого заключается в том, чтобы каждый проект мог загрузить модуль и получить текущий инъецируемый интерфейс.

App_Start/NinjectWebCommon.cs (в проекте MVC)

private static void RegisterServices(IKernel kernel)
{
    var modules = new IoCModules();
    var newKernal = modules.GetKernel();

    kernel = newKernal;
}

IoCModules.cs (в проекте Project.Ioc)

public class IoCModules
{
    public IKernel GetKernel()
    {
        var modules = new CoreModule();
        return modules.Kernel;
    }
}

CoreModule.cs (в проекте Project.IoC.Modules) < - Здесь все ссылки на все проекты, это обойти любые проблемы с круговой зависимостью.

public class CoreModule : NinjectModule
{
    public override void Load()
    {
       Bind<IHardwareService>().To<WindowsHardwareService>();
       Bind<IStatusApi>().To<StatusApiController>();
    }
}

Но в настоящее время я получаю следующее:

Ошибка активации IHardwareService

Нет соответствующих привязок, и тип не является самопереключаемым. Путь активации:

2) Инъекция зависимости IHardwareService в службу параметров конструктора типа DashboardController

1) Запрос DashboardController

Предложения:

1) Убедитесь, что вы определили привязку для IHardwareService.

2) Если привязка была определена в модуле, убедитесь, что модуль загружен в ядро.

3) Убедитесь, что вы случайно не создали несколько ядер.

4) Если вы используете аргументы конструктора, убедитесь, что имя параметра совпадает с именем параметра конструктора.

5) Если вы используете автоматическую загрузку модуля, убедитесь, что путь поиска и фильтры правильные.

4b9b3361

Ответ 1

Кажется, у вас много вопросов, на что нужно ответить здесь, поэтому я постараюсь сделать все возможное.

В соответствии с вашим текущим вопросом я попытаюсь "составить" упрощенную архитектуру вашей текущей реализации:

  • Уровень домена: Ядро вашего домена, место вашего бизнеса и т.д.
  • Уровень инфраструктуры:. Здесь находятся ваши службы, например: WindowsHardwareService
    • IOC. Я склонен называть это как сборку DependencyResolution.
  • UI: приложение MVC

Предположим, что все это выше, мы можем заявить, что ваши приложения Composition Root или Entry point - это пользовательский интерфейс Проект MVC. Одно из основных понятий, использующее DI Container, которое вы инициализируете его в Composition Root, устанавливает/выполняет все необходимые привязки и регистрации здесь. Основное намерение сделать это в точке входа - избежать Service Locator anti-pattern.

Используя DI Container, вы не new() реализуете свои реализации класса или получаете ядро, а скорее запрашиваете зарегистрированную зависимость, следуя правилу Inversion Of Control или также известен как принцип Голливуда.

После курса философии мы можем, наконец, перейти к некоторой фактической реализации.

Создание Ninject module: в вашей сборке IOC, позвоните по этому вызову файл как ServiceModule.cs

using Ninject.Modules;
public class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IHardwareService>().To<WindowsHardwareService>();
        Bind<IStatusApi>().To<StatusApiController>();
    }
}

Это будет Ninject module, который вы зарегистрируете/загрузите в Composition Root.

Теперь о корне композиции: в UI проектах MVC NinjectWebCommon.cs У вас может быть метод, который отвечает за загрузку ваших модулей, как показано ниже.

private static void RegisterServices(IKernel kernel)
{
    var modules = new List<INinjectModule>
        {
            new ServiceModule()
            //, new FooModule()
            //, new BarModule()
        };

    kernel.Load(modules);
}  

И, наконец, ваш DashboardController в UI MVC:

public class DashboardController : Controller
{
    private readonly IHardwareService _hardwareService;

    public DashboardController(IHardwareService hardwareService)
    {
        _hardwareService = hardwareService;
    }
}

В этот момент попросите зарегистрированную реализацию IHardwareService в конструкторе контроллеров. DI Container выполнит грязное задание и передаст вам экземпляр, с которым вы сможете работать позже в своем контроллере.

Заметка о интерфейсах. Я склоняю их к собственной сборке, где я просто храню интерфейсы, например: Project.Domain.Interfaces или Project.Infrastructure.Interfaces, где каждая из этих сборок содержит только домен или интерфейсы инфраструктуры.

Ссылки между сборками:

Чтобы сопоставить все это, UI ссылается только на сборку IOC и сборку интерфейсов, которая содержит интерфейсы, которые вы связали в своем Ninject module.

Суммируя все вышесказанное:

Ваши классы и интерфейсы сами по себе являются просто частями, которые склеиваются с помощью контейнера DI.

Надеюсь, я немного это выяснил.

EDIT:, как хороший совет, который @AndreySarafanov указал в комментариях, если вам нужны разные реализации интерфейса, который вы запрашиваете в конструкторе, вы можете использовать Ninject Factory. Для получения дополнительной информации вы можете обратиться к этому.