I am wondering how to properly use abstract factories when using the DI infrastructure, and one of the parameters in this factory is the dependency that should be handled by the DI framework.
I am not sure what to do my abstract factory to completely omit the parameter, and then use my DI container to connect it, or should I pass an object dependency.
For example, I have TcpServer and it uses Session.Factory to create sockets. The Session object actually accepts the processor in its constructor. Should I transfer the Processor to TcpServer, then transfer it to Session.Factory or will my DI container post?
If I had a DI container, the wiring would be like this:
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()); ... } }
Then, using a DI container like Ninject, I could do this when setting up the container:
Bind<Session.Factory>().ToMethod(c => { var processor = Kernel.Get<Processor>(); return (name) => new Session(name, processor); }).InSingletonScope();
My main problem with this approach is that it assumes that anyone who creates Session.Factory knows about the processor. In my case, since I use a DI container, it is actually very convenient, but it seems strange to have a factory of its own dependencies. I always imagined that the factory does not have any members.
If I had to pass the dependency through
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); ... } }
I have two questions with a second approach:
- TcpServer does virtually nothing with the processor. He just passes it on. It seems like this is a bad DI person at work almost.
- In a real program of this code, the processor actually has a link to TcpServer. Therefore, when using this approach, I get a circular link. When I break it using the first script, this is not a problem.
What do you think is the best approach? I am open to new ideas.
Thanks!