Мне интересно, как правильно использовать абстрактные фабрики при использовании инфраструктуры DI, и один из параметров в этой фабрике - это зависимость, которая должна обрабатываться инфраструктурой DI.
Я не уверен, следует ли заставить мою абстрактную фабрику полностью опускать параметр, а затем использовать мой DI-контейнер для его соединения или я должен передать зависимость объекту.
Например, у меня есть TcpServer, и он использует Session.Factory для создания сокетов.Объект Session фактически принимает Processor в своем конструкторе.Должен ли я передать процессор процессору TcpServer, а затем передать его на Session.Factory или сделать так, чтобы мой контейнер DI выполнил монтаж?например:
class Session : ISession
{
public delegate ISession Factory(string name);
...
public Session(string name, Processor processor)
{
...
}
}
class TcpServer : ITcpServer
{
private readonly Session.Factory _sessionFactory;
public TcpServer(Session.Factory sessionFactory)
{
this._sessionFactory = socketFactory;
}
...
public void OnConnectionReceived()
{
...
var session= _sessionFactory(ip.LocalEndPoint());
...
}
}
Затем, используя DI-контейнер, такой как Ninject, я смогу сделать это при настройке контейнера:
Bind<Session.Factory>().ToMethod(c =>
{
var processor = Kernel.Get<Processor>();
return (name) => new Session(name, processor);
}).InSingletonScope();
Моя главная проблема с этим подходомв том, что он предполагает, что тот, кто создает Session.Factory, знает о процессоре.В моем случае, поскольку я использую DI-контейнер, это на самом деле очень удобно, но кажется странным иметь фабрику со своими собственными зависимостями.Я всегда представлял себе, что на фабрике вообще нет членов.
Если бы мне пришлось передать зависимость через
class Session : ISession
{
public delegate ISession Factory(string name, Processor processor);
...
public Session(string name, Processor processor)
{
...
}
}
class TcpServer : ITcpServer
{
private readonly Session.Factory _sessionFactory;
private readonly Processor _processor;
public TcpServer(Session.Factory sessionFactory, Processor processor)
{
this._processor = processor;
}
...
public void OnConnectionReceived()
{
...
var session = _sessionFactory(ip.LocalEndPoint(), _processor);
...
}
}
У меня есть две проблемы со вторым подходом:
- TcpServer фактически ничего не делает с процессором.Это просто передает это.Кажется, это почти что DI-код бедняков на работе.
- В реальной программе, стоящей за этим кодом, у Processor есть ссылка на TcpServer.Поэтому при использовании этого подхода я получаю круговую ссылку.Когда я разбиваю его на части с помощью первого сценария, это не проблема.
Какой, по вашему мнению, лучший подход?Я открыт для новых идей.
Спасибо!