вопрос по IoC - PullRequest
       51

вопрос по IoC

0 голосов
/ 09 июня 2011

Я полагаюсь на шаблон IoC в течение 1 года, используя structmap & asp.net mvc.IoC действительно аккуратен, особенно если у вас много зависимостей в вашем классе, просто вставьте зависимость в ваш конструктор и все готово, IoC автоматически введет его для вас.

Мой вопрос заключается в том, что я использую asp.net mvc с классом контроллера, имеющим зависимости IServices.

Мне нужны службы зависимостей только для определенного действия контроллера, скажем «/ customer / add», но мне не нужны эти зависимости от других действий, скажем «/ Клиент / Index».Однако, поскольку я использую DI (внедрение зависимости) в конструкторе, зависимости всегда создаются, даже если они мне не нужны.Это хорошо?Создание объекта стоит дорого и занимает много памяти.

Конечно, я могу делать container.GetInstance внутри действия, но это не очень хорошая практика, так как вы будете сильно зависеть от IoC в своем коде и модульном тестировании.

Есть предложения?поправьте меня, если я с чем-то не прав.

Ответы [ 5 ]

4 голосов
/ 09 июня 2011

Я всегда использую конструкторы.Свойства imho следует использовать только для решения циклических зависимостей.

Причина в том, что цель не ясна при использовании свойств.Ничто в вашем коде не говорит, что MyController.DoThat не будет работать, если свойство MyController.MyProperty не установлено.

Если для метода требуется определенная служба, то эта служба требуется для всего вашего класса.В противном случае вы нарушите контракт, который выставляет ваш класс.

4 голосов
/ 09 июня 2011

Обновлено в ответ на комментарий jgauffins

Я вижу два простых способа решения вашей проблемы:

Добавьте фабрику сервисов в конструктор и создайте сервис по требованию.

interface IFooService
{
    void Bar();
}

interface IFooServiceFactory
{
    IFooService CreateFooService();
}

class YourController
{
    public YourController(IFooServiceFactory fooServiceFactory)
    {
        this.fooServiceFactory = fooServiceFactory;
    }

    public void YourAction()
    {
        IFooService fooService = this.fooServiceFactory.CreateFooService();
        fooService.Bar();
    }
}

Внедрите прокси-сервер службы в конструктор и позвольте прокси-серверу создавать реальный сервис по требованию.

interface IFooService
{
    void Bar();
}

class FooServiceProxy : IFooService
{
    private IFooService realFooService;


    void IFooService.Bar()
    {
         IFooService realFooService = GetRealFooService();
         realFooService.Bar();
    }

    private IFooService GetRealFooService()
    {
        if(this.realFooService == null)
        {
            this.realFooService = CreateRealFooService();
        }
        return this.realFooService;
    }

    private IFooService CreateRealFooService()
    {
        // You could inject the service factory in the constructor of the proxy and use it here to create the real service.
    }
}

class YourController
{

                          Inject FooServiceProxy here
                          v
                          v 
    public YourController(IFooService fooService)
    {
         this.fooService = fooService;
    }

    public void YourAction()
    {
         this.fooService.Bar();
    }
}
3 голосов
/ 09 июня 2011

зависимости всегда создаются, даже если они мне не нужны. Это хорошо?

Хотя не каждая часть класса требует зависимости, сам класс нуждается в этой зависимости, и поэтому не является необязательной зависимостью. Обычно, когда вы видите, что некоторые зависимости используются в одной части класса, а другие - в другой, ваш класс может нарушать SRP ; это может делать больше, чем одну вещь. Однако их разделение, вероятно, не поможет, поскольку классы MVC Controller больше ориентированы на интерфейсы, поэтому я бы просто оставил все как есть.

Создание объекта обходится дорого и занимает много памяти.

Типы ссылок всегда имеют 8-байтовые издержки (на 32-битной платформе), так что это немного. Сервисный объект, который вы обычно внедряете, содержит очень мало состояний, часто только некоторые значения конфигурации и ссылки на их зависимости. С точки зрения памяти, это ничто по сравнению с данными, которые проходят через ваше приложение (например, данные из базы данных или строки, которые генерируются MVC для построения HTML). Это зависит от используемой вами структуры DI, но обычно даже относительно большой граф зависимостей генерируется за доли секунды. И даже когда построение графиков занимает слишком много времени, существуют и другие способы оптимизации производительности. Например, подумайте о том, чтобы определить некоторые услуги с единым стилем жизни. Когда этого недостаточно, вы можете рассмотреть возможность перехода на более быструю структуру DI. StructureMap, однако, является одним из более быстрых DI-контейнеров в поле (из наиболее известных), поэтому для нормальной разработки приложений это не должно быть проблемой.

1 голос
/ 09 июня 2011

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

0 голосов
/ 11 июня 2011

StructureMap поддерживает отложенное создание экземпляров - не нужно создавать собственное решение для фабрики услуг / прокси-сервера. Если вы хотите, чтобы экземпляр IService создавался только в тех действиях, в которых он используется, вместо этого вставьте Func<IService> в ваш конструктор. Затем в своем действии, которое нуждается в этом, вызовите Func для возврата экземпляра.

class CustomerController {
  Func<IService> _service;

  public CustomerController(Func<IService> service){
    _service = service;
  }

  public ActionResult Index(){
    _service().CallMethodOnService();
  }
}

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

...