Является ли инъекция зависимости полезной в С++

С# использует Injection Dependency (DI), чтобы иметь без потерь и тестируемую платформу. Для этого мне понадобится interface и, возможно, DI или контейнер с инверсией управления (IoC) для разрешения моих экземпляров.

Но как вы это делаете в С++? Я немного об этом читал, и кажется, что инъекция зависимостей на С++ не такая большая тема, как в С#. В С++ вы используете ссылку на объект - это способ использовать DI в С++, правильно?

Если моя теория со ссылками правильна, есть ли что-то вроде контейнера, где я могу разрешить все ссылки? В С# у меня есть "bad class/bad project/assembly", который регистрирует все мои экземпляры в статическом контейнере при запуске программы. Затем, в каждом классе, я могу экземпляр статического контейнера и может разрешить конкретный экземпляр, возможно ли это на С++?

Используете ли вы инъекцию зависимостей (или то, что она называется) в С++? Если да, как вы его используете? Есть ли сходство с С#?

Ответ 1

Для этого мне нужен интерфейс и, возможно, контейнер для разрешения моих экземпляров. Но как вы это делаете в С++?

Таким же образом. Разница в том, что там, где вы "программируете интерфейс" на С#, вы "программируете базовый класс" на С++. Кроме того, у вас есть дополнительные инструменты на С++, которых у вас нет на С# (например, шаблоны на основе политик реализуют инъекцию зависимостей, выбранную во время компиляции).

В С++ вы используете ссылку на объект, это способ использовать DI в С++, правильно?

Нет; это не способ использовать DI, это способ использовать DI в С++.

Также рассмотрим:

  • используйте указатель на объект (или интеллектуальный указатель, в зависимости от случая)
  • используйте аргумент шаблона для политики (например, см. использование std:: default_delete в интеллектуальных указателях)
  • используйте лямбда-калькулл с инъецированными функторами/предикатами.

В С# у меня есть "плохой класс/плохой проект/сборка", который регистрирует весь мой экземпляр в статическом контейнере при запуске программы.

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

возможно ли это в С++?

Да, это вполне возможно (но вы не должны этого делать, из-за нарушения закона Деметры). Посмотрите на boost:: any (это позволит вам хранить гетерогенные объекты в контейнере, подобно хранению объектов по ссылке object в С#).

Используете ли вы инъекцию зависимостей или что-то еще, что она вызывается в С++?

Да (и это называется инъекцией зависимостей:)).

Если да, как вы его используете?

Как я описал выше (аргументы шаблона политики, инъецируемые функторы и предикаты как компоненты многократного использования, вводя объекты по ссылке, указательный умный указатель или значение).

Ответ 2

Использование инъекции зависимостей довольно просто в С++. Просто определите интерфейс (чистый абстрактный базовый класс), который вы используете в качестве аргумента ссылки или указателя (или умного указателя) для конструктора или функции init из класса, в который вы хотите ввести зависимость.

Затем, в unit test, введите mock-объект (экземпляр класса, наследующего из абстрактного класса интерфейса), и в реальном коде введите инстанс реального класса (также наследующий от того же класса интерфейса).

Easy-Peasy.

Ответ 3

Да, инъекция зависимостей также полезна в С++. Нет причин, по которым это не должно быть, потому что ему не нужен конкретный язык или синтаксис, а просто объектно-ориентированная архитектура классов (по крайней мере, это, пожалуй, самый обычный случай).

В то время как на С# есть только "указатели" на динамически выделенные объекты, С++ имеет несколько вариантов, таких как "обычные" локальные переменные, несколько типов указателей, ссылок... кроме того, понятие семантики перемещения очень важно для этого.

В С++ вы используете ссылку на объект, это способ использовать DI в С++, правильно?

Не только. Вы можете использовать все, что хотите, до тех пор, пока вы можете передать что-то методу класса, и это что-то будет существовать до тех пор, пока объект класса. Все три возможности выше могут сделать это (каждый из них с определенными ограничениями)

есть что-то вроде контейнера, я могу разрешить все это Рекомендации? В С# у меня есть "плохой класс/плохой проект/сборка", который зарегистрируйте весь мой экземпляр в статическом контейнере

Может быть, вам не хватает смысла инъекции зависимостей. Это не то же самое, что куча "глобальных" переменных. Но да, конечно, это возможно и на С++. Есть классы, есть static, и это все, что нужно.

Ответ 4

С С++ 11 как предел проекта я закончил свой собственный. Я свободно основал его на .NET Ninject API без отражения.

ServiceLocator

Обратите внимание, что хотя он называется ServiceLocator (так как он не выполняет Injection Injection сам), если вы используете привязки функции lambda, а предпочтительно классы ServiceLocator:: Module, вы получаете Injection (не основанный на отражении) и действительно работает очень хорошо (IMO)