听起来您应该改用观察者模式,让消费者决定将哪个数据包发送到哪里。
// implement this interface in all forms
public interface IPacketSubscriber
{
void HandlePacket(Packet packet);
}
// like this
public class SomeForm : Form, IPacketSubscriber
{
public SomeForm()
{
// subscribe in some way here.
YouSingleton.Consumer.Subscribe(1, this);
YouSingleton.Consumer.Subscribe(12, this);
YouSingleton.Consumer.Subscribe(25, this);
}
public void HandlePacket(Packet packet)
{
// got packet here
}
}
// Keeps track of all subscribers
public class SubscriberList
{
Dictionary<int, List<IPacketSubscriber>> _subscribers
= new Dictionary<int, List<IPacketSubscriber>>();
public void Subscribe(int packetId, IPacketSubscriber subscriber)
{
List<IPacketSubscriber> subscribers;
if (!_subscribers.TryGetValue(packetId, out subscribers))
{
subscribers = new List<IPacketSubscriber>();
_subscribers.Add(packetId, subscribers);
}
subscribers.Add(subscriber);
}
public void Publish(Packet packet)
{
List<IPacketSubscriber> subscribers;
if (!_subscribers.TryGetValue(packet.FunctionId, out subscribers))
{
subscribers = new List<IPacketSubscriber>();
_subscribers.Add(packet.FunctionId, subscribers);
}
foreach (var subscriber in subscribers)
{
subscriber.HandlePacket(packet);
}
}
}
// changes in the consumer class
// composite pattern & law of demeter, do not expose the subscriberlist
public class Consumer
{
SubscriberList _subscribers = new SubscriberList();
public void Subscribe(int packetId, IPacketSubscriber subscriber)
{
if (subscriber == null) throw new ArgumentNullException("subscriber");
_subscribers.Subscribe(packetId, subscriber);
}
protected void OnReceivedCompletePacket(Packet packet)
{
_subscribers.Publish(packet);
}
}
但是,您可以将事情进一步解耦。表单并不需要真正了解消费者,只需知道它们可以从某个地方接收事件。让我们使用这些知识并创建另一个接口:
public interface IPacketDispatcher
{
void Subscribe(int packetId, IPacketSubscriber);
}
然后简单地更改以便表单使用接口(取决于您如何将调度程序/消费者暴露给表单)。
这个微小的改变使得测试你的表单和改变你将来接收数据包的方式变得非常容易。