使用委托来模拟连接的对象
本文关键字:连接 对象 模拟 | 更新日期: 2023-09-27 18:07:09
我正在编写一个应用程序,其中我需要在以任意方式相互连接的大型对象网络中模拟电力或天然气等资源的分布。不需要模拟物理。当对象请求资源时,资源单位的流动。
考虑下面的图:
ObjA <---> ObjB <---> PwrA <---> ObjF
/' ObjG
ObjE<---/ '---> PwrB
当Obj对象请求时,Pwr对象可以提供资源电。我在这里需要模拟的是,如果ObjA需要50个电力,它应该向所有连接的对等体发送消息,而不关心它去了谁,并且应该只从直接或间接连接的对等体获取资源。
我没有在这里模拟延迟或任何东西,所以传输将是即时的。从编程的角度来看,这在应用程序中完全是本地的(没有真正的网络或类似的东西)。
我在这里的挑战是试图以模块化和干净的方式编程。如果可能的话,我希望避免本地连接节点的庞大列表和关于如何处理消息的大型ifelse语句。
我既想实现我的目标,也想学一些新的东西。几个星期以来,我一直在阅读文章、书籍和编程概念,我认为c# delegate可能是一个很棒的解决方案。
我已经做了一些原型,并设法用MessageOut委托设置对象,其他连接的对象可以订阅和侦听传出的消息来处理。
这工作得很好,但由于我对这个概念的经验不足,我有以下缺点:
- 我不知道如何处理在连接对象之间传递消息的循环引用:在上面的图中,如果ObjB广播一个消息用于电力ObjA, PwrA, PwrB, ObjE将被通知,这将依次所有进程,然后通知ObjB。这将反过来通知……等等。网络处理这种情况的方法是简单地广播出除了接收它的端口之外的所有端口(侦听委托的对象)。我如何用委托实现这个?平面广播不起作用。
- 监听委托有效地创建单向通信。为了实现双向通信,我需要让对象彼此侦听传出的消息。但是如果没有上面,上面肯定是另一个循环参考?
在我看来,委托将是笨拙和混乱的。
你看过TPL数据流吗?http://msdn.microsoft.com/en-gb/library/hh228603.aspx
它提供了许多具有排队请求,发送请求等行为的"块",您可以使用它来模拟这些虚拟资源的推和拉。
将它们连接在一起以及处理循环依赖关系的所有魔法都被处理好了。
如果你正在处理事件,你会注意到最好的做法是在每个事件委托中都有一个"sender"对象和一个"EventArgs"。
我曾经做过类似的事情,出现的解决方案是将"OriginalSender"添加到EventArgs派生类中。
每个收到的消息首先传递给if语句:
class MyEventListenerClass
{
.....
private void EventHandlerMethod(object sender, MyEventArgs E)
{
if (E.OriginalSender != this)
{
do what is needed
}
else
{
got this message from myself in a circular way....discard it
}
}
......
}
class MyEventArgs : EventArgs
{
public object OriginalSender {get; private set;}
public MyEventArgs(object OrigSender) : base ()
{
OriginalSender = OrigSender;
}
}
但这并不能解决所有问题。在我的例子中,没有任何不包含原始发送者的循环。如果信息陷入这样的循环,它将是无限的。也许一个发送者列表可以解决这个问题,使if (E.SenderList.Contains(this)) {...}
。因此,每次接收到消息时,接收方都会检查列表中是否包含自己。如果没有,他发送消息,并将自己添加到发送者列表中。
看来你的思路是对的。它实际上被称为观察者/倾听者设计模式…你应该在c#中使用Events来更好地实现这个模式。事件基本上是一种委托你可以在MSDN或Google找到更多信息…
关于圆度问题:
你的屏蔽只是传递发送者的列表随着消息…每个侦听对象都必须检查他是否在该列表中的发送者之一,并决定他是否也应该发送Massey。
我不认为委托是解决你提出的问题的好办法。让我们看一下下面的场景:
ObjB需要1个电力单位,现在,让我们假设它有一个名为"GetElectricity"的委托,正如我从你写的理解,PwrA, PwrB都为委托添加了一个处理程序,PwrA和PwrB处理程序都将被调用,或者你将尝试第一个处理程序,如果它没有提供所需的电力,它将尝试下一个…这将创建一个复杂的,难以维护的软件。
你在说些什么(或者至少,我会做什么:)),事件,ObjB NeedElecricty将提高一个事件,所有压水式反应堆对象注册,如果他们可以提供elecricity会调用事件"ProvideElectricity"ObjB,比ObjB可以决定,其中一个他将他所需要的权力,并告知他们,他需要从PwrA 1动力装置(会告诉PwrB,他不需要it服务)。
寻找观察者和事件,因为这是你主要谈论的。
我同意@Clint, TPL数据流是最好的解决方案,因为它确实做到了你所说的。