我正在编写一个应用程序,我需要模拟在以任意方式相互连接的大型对象网络中的电力或气体等资源的分布。不需要模拟物理学。只是当对象要求它们时资源单元的流动。
考虑下图:
ObjA <---> ObjB <---> PwrA <---> ObjF
/\ ObjG
ObjE<---/ \---> PwrB
当 Obj 对象询问时, Pwr 对象可以提供电力供应。 我需要在这里模拟的是,如果ObjA需要50电,它应该向所有连接的对等体发送消息而不关心它是谁,并且应该仅从它直接或间接连接的对等体获得资源。
我不是在这里模拟延迟或任何事情,所以传输将是即时的。从编程的角度来看,这在应用程序中完全是本地的(没有真正的网络或类似的东西)。
我的挑战是尝试以模块化和干净的方式对其进行编程。我想避免使用本地连接节点的巨大列表以及如果可能的话如何处理消息的大型ifelse语句。
我想要实现我的目标并学习新的东西。我已经阅读了几周的文章,书籍和编程概念,我认为可能是一个很棒的解决方案是C#代表。
我做了一些原型设计并设法使用MessageOut Delegate设置对象,其他连接对象可以订阅并侦听要处理的外发消息。
这很有效,但由于我对这个概念的经验,我有以下缺点:
答案 0 :(得分:3)
在我看来,代表们会很笨拙和混乱。
你看过TPL Dataflow吗? http://msdn.microsoft.com/en-gb/library/hh228603.aspx
它提供了许多具有排队请求,发送请求等行为的“块”,您可以使用它来模拟这些虚拟资源的推送和拉动。
将所有连接在一起并处理循环依赖关系的所有魔力都得到了解决。
答案 1 :(得分:1)
如果您正在处理活动,您会注意到最佳做法是在每个活动代表中都有一个“发件人”对象和一个“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)) {...}
。
因此,每次收到消息时,接收方都会检查列表是否包含自身。如果没有,他会将消息添加到发件人列表中。
答案 2 :(得分:0)
似乎你在正确的轨道上..它是实际的,称为观察者/听众设计模式......你应该使用C#中的事件来更好地实现该模式。事件基本上是一种代理类型,您可以在MSDN或Google中找到更多信息...
关于循环问题:
你屏蔽只是传递一个发件人列表和消息..并且列表中的每个对象都必须检查他是否是该列表中的发件人之一,并决定他是否应该传输Massey天气。< / p>
答案 3 :(得分:0)
我认为代表们不是解决您提出的问题的好方法。 让我们看一下以下场景:
ObjB需要1个电力单元,现在,让我们假设它有一个名为“GetElectricity”的代表,据我所知,PwrA,PwrB都为代表添加了一个处理程序,PwrA和PwrB处理程序都将是调用,或者你将尝试第一个处理程序,如果它没有提供所需的电力,它将尝试下一个...这将创建一个复杂的,难以维护的软件。
你在谈论什么(或至少,我会做什么:)),是事件,ObjB将为NeedElecricty举办一个事件,所有Pwr对象都注册了它,如果他们可以提供电子,他们会称之为ObjB上的事件“ProvideElectricity”,比ObjB可以决定从哪一个他将需要的电力,并通知他们他需要PwrA的1个电源单元(并告诉PwrB他不需要它服务)。
寻找观察者和事件,因为这是你主要谈论的内容。
我同意@Clint,TPL数据流是最好的解决方案,因为它正是你所说的。但正如你所说它超出了范围。