我有一个用C#编写的客户端和服务器类。两者都需要相互通信(将来有几个客户端将与服务器通信)。但是我遇到了循环依赖。因为我使用unity进行依赖注入,所以我的程序冻结并崩溃了。
我试图使用客户端和服务器之间的接口作为消息提供者。但无论如何还是会崩溃,因为该接口的实现引用了客户端和服务器,并且引用了该接口。
该项目确实很大,但我尝试将其削减:
public class Client
{
private Server server;
public Client(Server server)
{
this.server=server;
}
public SendToServer(string message)
{
server.Receive(message);
}
public Receive(string message)
{
}
}
public class Server
{
private Client client;
public Server(Client client)
{
this.client=client;
}
public SendToClient(string message)
{
client.Receive(message);
}
public Receive(string message)
{
}
}
所有这些都在WPF中的UserControl内部运行。客户端被注入到视图的构造函数中。然后,Unity将Server注入到Client构造函数中,这将触发Server构造函数,而Server构造函数将再次触发Client构造函数。
public partial class ClientView: UserControl
{
public ClientView(Client client)
{
this.DataContext = client;
InitializeComponent();
}
}
答案 0 :(得分:3)
乍一看,这似乎很可疑,但是如果您使用的是这种组合,则需要以某种方式打破依赖性循环。
一种方法是创建依赖关系的抽象,并对一个不依赖于另一个的实现进行多种实现。例如
public interface IServer { void Receive(string message); void SendToClient(string message); }
public interface IClient { void Receive(string message); void SendToServer(string message); }
public class Client : IClient
{
// This will be set as SimpleServer-implementation
private readonly IServer _server;
public Client(IServer server) => _server = server;
public void SendToServer(string message) => _server.Receive(message);
public void Receive(string message) => Console.WriteLine($"Client received: {message}");
}
public class Server : IServer
{
private readonly IClient _client;
public Server(IClient client) => _client = client;
public void SendToClient(string message) => _client.Receive(message);
public void Receive(string message) => Console.WriteLine($"Server received: {message}");
}
public class SimpleServer : IServer
{
public void SendToClient(string message) { }
public void Receive(string message) => Console.WriteLine($"SimpleServer received: {message}");
}
void Main()
{
var container = new UnityContainer();
container.RegisterType<IServer, Server>();
container.RegisterType<IClient, Client>(new InjectionConstructor(container.Resolve<SimpleServer>()));
var server = container.Resolve<IServer>();
var client = container.Resolve<IClient>();
server.SendToClient("Foo");
client.SendToServer("Bar");
}
处理此问题的另一种方法是在工厂的帮助下延迟初始化一个依赖项。这样,我们可以在第一次使用依赖项时延迟加载它。在下面的示例中,我将Func
委托用作工厂并将其包装在Lazy
中。
public interface IServer { void Receive(string message); void SendToClient(string message); }
public interface IClient { void Receive(string message); void SendToServer(string message); }
public class Client : IClient
{
private readonly IServer _server;
public Client(IServer server) => _server = server;
public void SendToServer(string message) => _server.Receive(message);
public void Receive(string message) => Console.WriteLine($"Client received: {message}");
}
public class Server : IServer
{
private readonly Lazy<IClient> _client;
public Server(Func<IClient> clientFactory)
=> _client = new Lazy<IClient>(() => clientFactory());
public void SendToClient(string message) => _client.Value.Receive(message);
public void Receive(string message) => Console.WriteLine($"Server received: {message}"); }
}
void Main()
{
var container = new UnityContainer();
container.RegisterType<IClient, Client>();
container.RegisterType<IServer, Server>();
var server = container.Resolve<IServer>();
var client = container.Resolve<IClient>();
server.SendToClient("Foo");
client.SendToServer("Bar");
}