Is it a bad practice to set dependencies to NULL in a IoC container and supply the dependencies at runtime?

偶尔善良 提交于 2019-12-02 00:16:12

It's best to compose complete object graphs right from the start. Injection of null values should be prevented, because it complicates the consuming class.

In your case, however, it seems like the Socket is not a 'real' component, but rather runtime data. As described here, you should prevent injecting runtime data into the object graph during construction.

That article gives two solutions to work around that problem, but there are more solutions. Abstract factories are, however, typically not a good solution, as you already alluded, and this blog post describes in more general sense what the problem is with Abstract Factories. Chapter 6.2 of this book even goes into more details about the problem with Abstract Factories from a DI point of view.

A solution given in the blog post is the use of a 'context' abstraction. In your case, for instance, a SocketContext interface that allows you to get the Socket runtime value by a consumer, once that consumer's methods are called, and thus after the consumer's object graph is constructed. For instance:

public interface SocketContext
{
    Socket get_CurrentSocket();
}

Another option is to use a Proxy class that either hides the real Socket or the real SocketManager (depending on which level you can place the Proxy). This allows a consumer to be unaware that some piece of runtime data needs to be initialized under the covers and that it might be done lazily once the first call is made. For instance:

public class SocketManagerLazyProxy : SocketManager
{
    private SocketManager mananger;

    public void DoSomething()
    {
        if (manager == null) manager = new RealSocketManager(new Socket());
        manager.DoSomething();
    }   
}

Another option is to set the Socket value using Property Injection after the object graph is built. This allows you to construct the object graph much earlier in time, and set the runtime value once a request comes in, by setting it when a request comes in:

void HandleRequest(RequestData data)
{
    SocketManager manager = GetSocketManagerForThisRequest();
    manager.Socket = new Socket();
    Handler handler = GetHandler(data.Name);
    handler.Handle(data);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!