Какую инъекцию зависимостей использовать в «фабрике»? - PullRequest
1 голос
/ 25 февраля 2020

У меня есть два варианта создания фабрики ViewModel для внедрения в другие классы:

ОПЦИЯ A

public interface IFactory
{
    ViewModelA CreateViewModelA(string data);
    ViewModelB CreateViewModelB(string data);
}

public class MyFactory : IFactory
{
    public MyFactory(){}

    public ViewModelA CreateViewModelA(string data)
    {
        return new ViewModelA (data);
    }

    public ViewModelA CreateViewModelB(string data)
    {
        return new ViewModelB (data);
    }
}
//register factory
container.RegisterType<IFactory, MyFactory>(new ContainerControlledLifetimeManager());

ОПЦИЯ B

public interface IFactory
{
    T CreateViewModel<T>();
}
public class MyFactory : IFactory
{
    public MyFactory(IUnityContainer unityContainer)
    {
        _container = unityContainer;
    }
    private IUnityContainer _container { get; set; }

    public T CreateViewModel<T>()
    {
        return (T)this._container.Resolve<T>();
    }
}
//register factory
var container = new UnityContainer();
container.RegisterType<IFactory, MyFactory>(new ContainerControlledLifetimeManager(), new InjectionConstructor(container));
//inject this where neccessary

ОПЦИЯ B кажется проще реализовать, однако я не уверен, правильно ли использовать контейнер таким способом. Я читал об анти-паттерне сервисного локатора, и в этой ситуации способ, которым я передал контейнер в конструктор другого класса, похоже, напоминает эту проблему. Так какой вариант я должен go для и если возможно, чтобы уточнить, почему?

1 Ответ

1 голос
/ 25 февраля 2020

Опция A A по ряду причин:

Во-первых, в опции B MyFactory на самом деле ничего не делает. Даже общий c приведенный в return (T)this._container.Resolve<T>(); является избыточным, так что это не что иное, как Adapter over IUnityContainer. Во всем коде, в котором вы зависите от B версии IFactory, вы также можете напрямую зависеть от IUnityContainer (игнорируя Принцип разделения интерфейса на данный момент) .

Во-вторых, IUnityContainer (и, следовательно, также вариант B) является Service Locator, который является анти-шаблоном . Одна из проблем заключается в том, что предлагает бесконечное число методов , которые вы можете вызывать во время компиляции, но которые не будут работать во время выполнения. Это также нарушает инкапсуляцию .

Опция A, с другой стороны, не является локатором службы . Он предлагает только конечный API. Я бы, вероятно, вместо этого go с универсальным c интерфейсом:

public interface IFactory<T>
{
    T Create(object context);
}

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

Вы тратите гораздо больше времени на чтение кода, чем на его написание.

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