IOC - Должны ли классы утилит со статическими вспомогательными методами быть связаны с IOC? - PullRequest
27 голосов
/ 26 марта 2010

Просто пытаюсь все-таки разобраться с принципами МОК.

Q1: Статические методы - Должны ли служебные классы со статическими вспомогательными методами быть связаны с IOC?

Например, если у меня есть класс HttpUtils с несколькими статическими методами, должен ли я пытаться передать его другим классам бизнес-логики через IOC?

Следуйте на вопросы, это может быть:

Q2: Singletons - Как насчет таких вещей, как регистрация, когда вы можете получить к ней доступ через вызов типа Logger.getInstance (). Вы обычно оставляете это как есть, а НЕ используете IOC для внедрения регистратора в бизнес-классы, которые в этом нуждаются?

Q3: Статические классы - Я действительно не использовал эту концепцию, но есть какие-то рекомендации относительно того, как вы обычно справляетесь с этим, если переходите к подходу на основе IOC.

Заранее спасибо.

Ответы [ 4 ]

32 голосов
/ 27 марта 2010

Самое смешное в IoC состоит в том, что объекты, написанные в стиле, как правило, отделены от этих деталей.

Давайте используем в качестве примера служебный класс:

public class HttpUtils
{
    public static void DoStuff(int someValue)
    {
        // ...
    }
}

В приложениях, не ориентированных на IoC, вы можете использовать этот метод напрямую:

public class Foo
{
    public int Value { get; set; }

    public void DoStuff()
    {
        HttpUtils.DoStuff(Value);
    }
}

Однако это связывает определение DoStuff непосредственно с его реализацией. IoC стремится развести детали такого рода, поэтому вместо этого мы определяем операцию самостоятельно:

public interface IDoesStuff
{
    void DoStuff(int someValue);
}

Затем мы оставляем место в Foo для изменения реализации:

public class Foo
{
    private readonly IDoesStuff _doesStuff;

    public Foo(IDoesStuff doesStuff)
    {
        _doesStuff = doesStuff;
    }

    public int Value { get; set; }

    public void DoStuff()
    {
        _doesStuff.DoStuff(Value);
    }
}

Это отделяет Foo от HttpUtils. Реализатором концепции DoStuff теперь является деталь конфигурации, а не внутренняя зависимость (как в случае статического метода).

Обратите внимание, что Foo не знает, является ли его IDoesStuff одиночным или нет. Этот срок службы также является деталью конфигурации, а не неотъемлемой деталью Foo.

Подводя итог, обычно IoC и static расходятся, поскольку IoC способствует изменению, а static по определению предотвращает его. Объявите ваши зависимости в ваших конструкторах, и вы почти никогда не будете использовать функциональность static.

8 голосов
/ 15 июня 2010

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

1) Статические методы на вспомогательных классах - Нет, они не часто вводятся IoC. Обычно это утилиты без гражданства.

Чтобы использовать очень простой пример, вам не нужны две версии служебного метода с именем StringUtils.Reverse(). Вам нужен только один, и вы можете легко написать тесты вокруг него, потому что он не имеет состояния или зависимостей, поэтому абсолютно бесполезно его выводить из строя. Пример теста:

string reversedString = StringUtils.Reverse("input");
Assert.AreEqual("tupni", reversedString)

Если утилита на самом деле не имеет состояния (например, зависит от HttpContext.Current), то вы должны сделать зависимость явной, введя ее, а не сделав утилиту статичной.

2) Синглтоны : Часто да, синглтоны вводятся инъекцией. Но хорошо в IoC то, что вы меньше беспокоитесь о том, есть ли что-то одно или нет. Вы получаете гибкость в создании экземпляров с помощью IoC. Решение о том, чтобы каждый раз иметь конкретный тип в виде одиночного или нового экземпляра, становится частью конфигурации контейнера IoC, и больше ничего в коде не нужно менять.

Таким образом, синглтон-капот перестает быть отдельной проблемой, которая должна быть закодирована в классе (а классы, имеющие несколько проблем, когда им не нужно, это плохо), и это становится проблемой контейнера IoC. Вы больше не кодируете класс «как синглтон» с чем-то особенным, таким как приватный конструктор и метод public static GetInstance(), вы просто кодируете его для основной задачи, в то время как конфигурация контейнера IoC указывает, является ли он синглтоном или нет или где-то посередине, например, один экземпляр на поток.

3) Статические классы - естественный дом для статических методов. Рассмотрите возможность создания методов расширения статических методов там, где это необходимо. Вы не можете внедрить эти классы, так как вы не можете их создать. Использование статических классов создает процедурный не объектно-ориентированный код. Это не плохо для небольших вспомогательных методов, но если большая часть кода такая, то вы не используете мощные функции OO платформы .Net.

2 голосов
/ 17 июня 2010

Статические методы по определению не нуждаются в экземпляре. DI / IOC стремится удовлетворить интерфейсы с конкретными классами, и учитывая, что ваш статический класс вместе со своими статическими методами по определению не может реализовать интерфейс или расширить класс, вопрос не имеет смысла. Нет смысла передавать вспомогательный класс, потому что не требуется экземпляр для использования статических методов. Ваш код всегда будет выполнять одни и те же методы статического помощника даже без экземпляра.

В приложении, работающем с IOC / DI, можно определить интерфейсы и иметь хотя бы одну реализацию. Все дело в управлении экземплярами и их зависимостями.

0 голосов
/ 05 ноября 2013

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

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

Самому потреблению классов может даже не потребоваться доступ к БД. Поэтому я не хочу вводить средство доступа к базе данных и передавать его в классы утилит.

Думаю, пока нет идеального решения. Однажды я надеюсь, что мы пойдем еще дальше, в дополнение к внедрению конструктора / свойства, есть «внедрение / конфигурация глобального контекста» или «статическое внедрение», применяя Ioc помимо создания объекта.

Подумай, а почему нет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...