dependency-injection - управления - принцип инверсии зависимостей c#




Инверсия контроля против инъекции зависимостей (12)

Согласно статье, написанной Мартином Фаулером , инверсия управления - это принцип, в котором управляющий поток программы инвертируется: вместо программиста, контролирующего поток программы, внешние источники (каркас, службы и другие компоненты) берут на себя управление Это. Это похоже на то, что мы подключаем что-то еще. Он упомянул пример EJB 2.0:

Например, интерфейс Session Bean определяет ejbRemove, ejbPassivate (хранится во вторичном хранилище) и ejbActivate (восстанавливается из пассивного состояния). Вы не можете контролировать, когда вызываются эти методы, только то, что они делают. Контейнер звонит нам, мы его не называем.

Это приводит к различию между каркасом и библиотекой:

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

Я думаю, точка зрения, что DI является IOC, означает, что зависимость объекта инвертирована: вместо этого он контролирует свои собственные зависимости, жизненный цикл ... что-то еще делает это для вас. Но, как вы рассказали мне о DI руками, DI не обязательно IOC. У нас все еще есть DI и нет МОК.

Однако в этой статье (из pococapsule, другой Framework IOC для C / C ++), это предполагает, что из-за IOC и DI контейнеры IOC и рамки DI намного превосходят J2EE, поскольку J2EE смешивает код структуры с компонентами , тем самым не делая его обычным старым Java / C ++ Object (POJO / POCO).

Инверсия контрольных контейнеров, отличных от шаблона инъекции зависимостей (ссылка на архив)

Дополнительное чтение, чтобы понять, в чем проблема со старой платформой разработки на основе компонентов, которая приводит ко второму документу выше: зачем и что из инверсии управления (ссылка на архив)

Мой вопрос : что такое IOC и DI? Я сбит с толку. Основанный на pococapsule, IOC является чем-то более значительным, чем просто инвертирует контроль между объектами или программистами и фреймворками.


// ICO, DI, 10 лет назад, это было так:

public class  AuditDAOImpl implements Audit{

    //dependency
    AuditDAO auditDAO = null;
        //Control of the AuditDAO is with AuditDAOImpl because its creating the object
    public AuditDAOImpl () {
        this.auditDAO = new AuditDAO ();
    }
}

Теперь с весной 3,4 или последним, как показано ниже

public class  AuditDAOImpl implements Audit{

    //dependency

     //Now control is shifted to Spring. Container find the object and provide it. 
    @Autowired
    AuditDAO auditDAO = null;

}

В целом, управление инвертируется от старой концепции связанного кода с такими фреймами, как Spring, что делает объект доступным. Так что это IOC, насколько я знаю, и инъекция зависимостей, как вы знаете, когда мы добавляем зависимый объект в другой объект, используя конструктор или сеттеры. Inject в основном означает передачу его в качестве аргумента. Весной у нас есть конфигурация на основе XML и аннотаций, где мы определяем объект bean и передаем зависимый объект с помощью стиля инсталляции Constructor или setter.


1) DI - Child-> obj зависит от parent-obj. Важен глагол. 2) IOC - Child-> obj выполняет под платформой. где платформа может быть школа, колледж, танцевальный класс. Здесь выполняется действие с различной импликацией под любым провайдером платформы.

практический пример: `

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

`

-AB


IOC (Inversion of Control) представляет собой концепцию шаблона проектирования для удаления зависимостей и их развязывания для обеспечения нелинейности потока и позволяет контейнеру / или другому объекту управлять предоставлением зависимостей. Это фактически следует за Голливудским директором «Не называй нас, мы позвоним тебе». Итак, суммируя различия.

Инверсия управления: - Это общий термин для развязки зависимостей и делегирования их подготовки, и это может быть реализовано несколькими способами (событиями, делегатами и т. Д.).

Инъекция зависимостей: - DI является подтипом IOC и реализуется путем инъекции конструктора, инъекции установщика или инъекции метода.

Следующая статья описывает это очень аккуратно.

source


Inversion of Control - это общий принцип проектирования архитектуры программного обеспечения, который помогает создавать многоразовые модульные программные среды, которые легко поддерживать.

Это принцип разработки, в котором поток управления «принимается» из общей библиотеки или кода многократного использования.

Чтобы понять это лучше, давайте посмотрим, как мы использовали код в наши предыдущие дни кодирования. В процедурных / традиционных языках бизнес-логика обычно контролирует поток приложения и «вызывает» общий или многоразовый код / ​​функции. Например, в простом консольном приложении мой поток управления контролируется инструкциями моей программы, которые могут включать вызовы некоторых общих функций многократного использования.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

В Contrast, с IoC, Frameworks являются многоразовым кодом, который «вызывает» бизнес-логику.

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

Хотя код рамки не знает о моей бизнес-логике, он все равно будет знать, как вызвать мой код. Это достигается с помощью событий / делегатов, обратных вызовов и т. Д. Здесь управление потоком «Перевернуто».

Таким образом, вместо зависимости потока управления от статически связанных объектов поток зависит от общего графа объектов и отношений между различными объектами.

Dependency Injection - это шаблон проектирования, который реализует принцип IoC для разрешения зависимостей объектов.

В более простых словах, когда вы пытаетесь написать код, вы будете создавать и использовать разные классы. Один класс (класс A) может использовать другие классы (класс B и / или D). Таким образом, классы B и D являются зависимостями класса A.

Простой аналогией будет класс Car. Автомобиль может зависеть от других классов, таких как Двигатель, Шины и многое другое.

Injection Dependency предполагает, что вместо зависимых классов (Class Car здесь), создающих его зависимости (Class Engine и класс Tire), классу следует вводить конкретный пример зависимости.

Давайте рассмотрим более практичный пример. Подумайте, что вы пишете собственный TextEditor. Помимо прочего, вы можете иметь проверку орфографии, которая предоставляет пользователю возможность проверить опечатки в его тексте. Простой реализацией такого кода может быть:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

На первый взгляд все выглядит розовым. Пользователь напишет некоторый текст. Разработчик захватит текст и вызовет функцию CheckSpellings и найдет список Typos, который он покажет пользователю.

Кажется, что все работает отлично до одного прекрасного дня, когда один пользователь начинает писать французский в редакторе.

Чтобы обеспечить поддержку для большего количества языков, нам нужно иметь больше SpellCheckers. Вероятно, французский, немецкий, испанский и т. Д.

Здесь мы создали тесно связанный код с «английским» SpellChecker, тесно связанным с нашим классом TextEditor, что означает, что наш класс TextEditor зависит от EnglishSpellChecker, или, другими словами, EnglishSpellCheker является зависимостью от TextEditor. Нам нужно удалить эту зависимость. Кроме того, нашему текстовому редактору нужен способ удержания конкретной ссылки любой проверки орфографии на основе усмотрения разработчика во время выполнения.

Итак, как мы видели во введении DI, это предполагает, что класс должен быть введен с его зависимостями. Таким образом, ответственный код должен вводить все зависимости вызываемого класса / кода. Таким образом, мы можем реструктурировать наш код как

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

В нашем примере класс TextEditor должен получить конкретный экземпляр типа ISpellChecker.

Теперь зависимость может быть введена в Constructor, Public Property или метод.

Давайте попробуем изменить наш класс с помощью Constructor DI. Измененный класс TextEditor будет выглядеть примерно так:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Чтобы вызывающий код при создании текстового редактора мог вводить соответствующий тип SpellChecker в экземпляр TextEditor.

Вы можете прочитать полную статью here


Короче говоря, IoC - это гораздо более широкий термин, который включает, но не ограничивается, DI

Термин «инверсия управления» (IoC) первоначально означал любой тип программирования, где общая структура или время выполнения контролировали поток программы

До того, как у ДИ было имя, люди начали ссылаться на фреймворки, которые управляют зависимостями как инверсия контрольных контейнеров, и вскоре значение IoC постепенно дрейфовало к этому конкретному значению: инверсия контроля над зависимостями.

Inversion of Control (IoC) означает, что объекты не создают другие объекты, на которые они полагаются, чтобы выполнять свою работу. Вместо этого они получают объекты, которые им нужны из внешнего источника (например, файл конфигурации xml).

Injection Dependency (DI) означает, что это делается без вмешательства объекта, обычно с помощью компонента инфраструктуры, который передает параметры конструктора и задает свойства.


Начнем с D SOLID и посмотрим на DI и IoC из книги Скотта Миллетта «Профессиональные шаблоны проектирования ASP.NET»:

Принцип инверсии зависимостей (DIP)

DIP - это все, чтобы изолировать ваши классы от конкретных реализаций и зависеть от них от абстрактных классов или интерфейсов. Он продвигает мантру кодирования к интерфейсу, а не к реализации, что повышает гибкость в системе, гарантируя, что вы не тесно связаны с одной реализацией.

Инъекция зависимостей (DI) и инверсия контроля (IoC)

Тесно связаны с DIP - принцип DI и принцип IoC. DI - это действие предоставления низкоуровневого или зависимого класса с помощью конструктора, метода или свойства. Используемые совместно с DI эти зависимые классы могут быть инвертированы для интерфейсов или абстрактных классов, что приведет к слабосвязанным системам, которые могут быть легко тестируемыми и легко меняющимися.

В IoC поток управления системой инвертируется по сравнению с процедурным программированием. Примером этого является контейнер IoC , целью которого является внедрение сервисов в клиентский код без наличия кода клиента, определяющего конкретную реализацию. Элемент управления в этом экземпляре, который является инвертированным, является действием клиента, получающего услугу.

Millett, C (2010). Профессиональные шаблоны проектирования ASP.NET. Wiley Publishing. 7-8.


Поскольку все ответы подчеркивают теорию, я хотел бы продемонстрировать пример первого подхода:

Предположим, мы создаем приложение, которое содержит функцию отправки сообщений подтверждения SMS после отправки заказа. У нас будет два класса: один отвечает за отправку SMS (SMSService), а другой отвечает за захват пользовательских входов (UIHandler), наш код будет выглядеть следующим образом:

public class SMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
    }
}

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        SMSService _SMSService = new SMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Вышеуказанная реализация не является ошибочной, но есть несколько проблем:
-) Предположим, что в среде разработки вы хотите сохранить SMS-сообщения, отправленные в текстовый файл, вместо использования шлюза SMS, для этого; мы в конечном итоге изменим конкретную реализацию (SMSService) с другой реализацией, мы теряем гибкость и вынуждены переписывать код в этом случае.
-) Мы закончим смешивание обязанностей классов, наш (UIHandler) никогда не должен знать о конкретной реализации (SMSService), это должно быть сделано за пределами классов, используя «Интерфейсы». Когда это будет реализовано, это даст нам возможность изменить поведение системы путем замены (SMSService), используемого с другой макетной службой, которая реализует один и тот же интерфейс, эта служба будет сохранять SMS-сообщения в текстовый файл вместо отправки на mobileNumber.

Чтобы исправить вышеуказанные проблемы, мы используем интерфейсы, которые будут реализованы нашими (SMSService) и новыми (MockSMSService), в основном новый интерфейс (ISMSService) будет показывать одинаковое поведение обоих сервисов как код ниже:

public interface ISMSService
{
    void SendSMS(string phoneNumber, string body);
}

Затем мы изменим нашу (SMSService) реализацию для реализации интерфейса (ISMSService):

public class SMSService : ISMSService
{
    public void SendSMS(string mobileNumber, string body)
    {
        SendSMSUsingGateway(mobileNumber, body);
    }

    private void SendSMSUsingGateway(string mobileNumber, string body)
    {
        /*implementation for sending SMS using gateway*/
        Console.WriteLine("Sending SMS using gateway to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

Теперь мы сможем создать новую макетную службу (MockSMSService) с совершенно другой реализацией, используя тот же интерфейс:

public class MockSMSService :ISMSService
{
    public void SendSMS(string phoneNumber, string body)
    {
        SaveSMSToFile(phoneNumber,body);
    }

    private void SaveSMSToFile(string mobileNumber, string body)
    {
        /*implementation for saving SMS to a file*/
        Console.WriteLine("Mocking SMS using file to mobile: 
        {0}. SMS body: {1}", mobileNumber, body);
    }
}

На этом этапе мы можем изменить код в (UIHandler), чтобы использовать конкретную реализацию службы (MockSMSService) легко, как показано ниже:

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        ISMSService _SMSService = new MockSMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

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

Чтобы достичь этого, нам необходимо реализовать изменение для нашего конструктора классов (UIHandler), чтобы передать ему через него, посредством этого код, который использует (UIHandler), может определить, какую конкретную реализацию (ISMSService) использовать:

public class UIHandler
{
    private readonly ISMSService _SMSService;

    public UIHandler(ISMSService SMSService)
    {
        _SMSService = SMSService;
    }

    public void SendConfirmationMsg(string mobileNumber)
    {
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Теперь форма пользовательского интерфейса, которая будет разговаривать с классом (UIHandler), отвечает за передачу какой реализации интерфейса (ISMSService) потреблять. Это означает, что мы инвертировали элемент управления, (UIHandler) больше не отвечает, чтобы решить, какую реализацию использовать, вызывающий код делает. Мы внедрили принцип инверсии управления, который является одним из его типов.

Код формы пользовательского интерфейса будет выглядеть следующим образом:

class Program
{
    static void Main(string[] args)
    {
        ISMSService _SMSService = new MockSMSService(); // dependency

        UIHandler _UIHandler = new UIHandler(_SMSService);
        _UIHandler.SendConfirmationMsg("96279544480");

        Console.ReadLine();
    }
}

Я нашел лучший пример на Dzone.com который очень полезен для понимания реальных различий между IOC и DI

«IoC - это когда у вас есть кто-то другой, создающий для вас объекты». Поэтому вместо того, чтобы писать в своем коде ключевое слово «new» (например, MyCode c = new MyCode ()), объект создается кем-то другим. Этот «кто-то еще» обычно называют контейнером IoC. Это означает, что мы передаем rrsponsibility (control) в контейнер, чтобы получить экземпляр объекта, называется Inversion of Control., Вместо того, чтобы вы создаете объект с помощью нового оператора, пусть это сделает контейнер.

   DI(Dependency Injection):  Way of injecting properties to an object is 
   called 
  Dependency injection.
   We have three types of Dependency injection
    1)  Constructor Injection
    2)  Setter/Getter Injection
    3)  Interface Injection
   Spring will support only Constructor Injection and Setter/Getter Injection.

Dzone.com и прочитать полную статью DI


DI и IOC - это два шаблона проектирования, которые в основном фокусируются на обеспечении несвязанной связи между компонентами или просто способе, в котором мы отделяем обычные отношения зависимости между объектом, чтобы объекты не были плотно друг к другу.

В следующих примерах я пытаюсь объяснить обе эти концепции.

Раньше мы пишем такой код

Public MyClass{
 DependentClass dependentObject
 /*
  At somewhere in our code we need to instantiate 
  the object with new operator  inorder to use it or perform some method.
  */ 
  dependentObject= new DependentClass();
  dependentObject.someMethod();
}

При инъекции зависимостей инжекторы зависимостей будут заботиться о создании объектов

Public MyClass{
 /* Dependency injector will instantiate object*/
 DependentClass dependentObject

 /*
  At somewhere in our code we perform some method. 
  The process of  instantiation will be handled by the dependency injector
 */ 

  dependentObject.someMethod();
}

Вышеупомянутый процесс предоставления контроля над каким-либо другим (например, контейнером) для инстанцирования и инъекции можно назвать «инверсией управления», а процесс, в котором контейнер IOC вводит зависимость для нас, можно назвать инъекцией зависимости.

IOC - это принцип, в котором поток управления программой инвертируется: вместо программиста, управляющего потоком программы , программа управляет потоком, уменьшая накладные расходы программисту. И процесс, используемый программой для инъекционной зависимости, называется DI

Эти две концепции работают вместе, предоставляя нам способ написать гораздо более гибкий, многоразовый и инкапсулированный код, который делает их важными понятиями при разработке объектно-ориентированных решений.

Также рекомендуем читать.

Что такое инъекция зависимости?

Вы также можете проверить один из моих подобных ответов здесь

Разница между инверсией контроля и зависимостями инъекций


IOC (Inversion of Controller): Предоставление контроля контейнеру для получения экземпляра объекта называется Inversion of Control. Означает, что вместо создания объекта с помощью нового оператора пусть контейнер сделает это для вас.

DI (Injection Dependency): передача требуемых параметров (свойств) из XML в объект (в POJO CLASS) называется инъекцией зависимостей.


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

Основными задачами, выполняемыми контейнером IoC, являются: создание экземпляра класса приложения. для настройки объекта. для сбора зависимостей между объектами.

DI - это процесс обеспечения зависимостей объекта во время выполнения с помощью инъекции установщика или инъекции конструктора.


IoC - Инверсия управления - это общий термин, независимо от языка, он фактически не создает объекты, а описывает, в каком объекте моды создается.

DI - Dependency Injection - это конкретный термин, в котором мы предоставляем зависимости объекта во время выполнения с использованием различных методов инъекции, а именно: Инжектор сеттера, инжекция конструктора или инжекция интерфейса.





inversion-of-control