最好从一开始就构建完整的对象图。注射null
应该避免使用值,因为它使消费类变得复杂。
然而,就你而言,这似乎是Socket
不是一个“真正的”组件,而是运行时数据。如上所述here,您应该防止在构造期间将运行时数据注入到对象图中。
该文章提供了两种解决方案来解决该问题,但还有更多解决方案。然而,抽象工厂通常是not正如您已经提到的,一个好的解决方案,并且这篇博文从更一般的意义上描述了抽象工厂的问题是什么。段落6.2 of 这本书甚至从 DI 的角度更详细地讨论了抽象工厂的问题。
博客文章中给出的解决方案是使用“上下文”抽象。例如,在您的情况下,SocketContext
接口,允许您获取Socket
一旦消费者的方法被调用,消费者的运行时值,因此after消费者的对象图被构建。例如:
public interface SocketContext
{
Socket get_CurrentSocket();
}
另一种选择是使用代理类,它可以隐藏真实的代理类Socket
或真实的SocketManager
(取决于您可以放置代理的级别)。这使得消费者不知道某些运行时数据需要在幕后初始化,并且在第一次调用时可能会延迟完成。例如:
public class SocketManagerLazyProxy : SocketManager
{
private SocketManager mananger;
public void DoSomething()
{
if (manager == null) manager = new RealSocketManager(new Socket());
manager.DoSomething();
}
}
另一个选项是设置Socket
构建对象图后使用属性注入来获取值。这允许您更早地构建对象图,并在请求到来时设置运行时值,方法是在请求到来时设置它:
void HandleRequest(RequestData data)
{
SocketManager manager = GetSocketManagerForThisRequest();
manager.Socket = new Socket();
Handler handler = GetHandler(data.Name);
handler.Handle(data);
}