2

我正在编写一个应用程序,我需要在其中模拟电力或天然气等资源在以任意方式相互连接的大型对象网络之间的分布。不需要模拟物理。只是当对象请求资源时资源单元的流动。

考虑下图:

ObjA <---> ObjB <---> PwrA <---> ObjF
            /\                                ObjG
   ObjE<---/  \---> PwrB

Obj对象请求时, Pwr对象可以提供资源电力。我在这里需要模拟的是,如果 ObjA 需要 50 电,它应该向所有连接的对等方发送一条消息,而不关心它去往谁,并且应该只从它直接或间接连接到的对等方取回资源。

我没有在这里模拟延迟或任何东西,因此传输将是即时的。从编程的角度来看,这完全是应用程序本地的(没有真正的网络或类似的东西)。

我在这里的挑战是尝试以模块化和干净的方式对其进行编程。我想避免本地连接节点的巨大列表和关于如何处理消息的大型 ifelse 语句(如果可能)。

我既想实现我的目标,又想学习一些新东西。几周以来,我一直在阅读文章、书籍和编程概念,我认为可能是一个很棒的解决方案是 C# Delegates。

我已经完成了一些原型设计并设法使用 MessageOut Delegate 设置对象,其他连接的对象可以订阅并侦听要处理的传出消息。

这工作得很好,但由于我对这个概念没有经验,我有以下缺点:

  • 我不知道如何处理连接对象之间的消息传递的循环引用: 上图中如果ObjB广播消息为电力ObjA,PwrA,PwrB,ObjE会被通知,依次所有处理,然后通知ObjB . 这将反过来通知...等。网络处理这个问题的方式是简单地广播所有端口(监听委托的对象),除了接收它的端口。我怎样才能用代表来实现呢?平面广播是行不通的。
  • 倾听代表有效地创建单向沟通。为了实现双向通信,我需要让对象互相监听传出消息。但是如果没有上述内容,它肯定是另一个循环引用吗?
4

4 回答 4

3

在我看来,代表会变得笨拙和混乱。

你看过 TPL 数据流吗?http://msdn.microsoft.com/en-gb/library/hh228603.aspx

它提供了许多具有排队请求、发送请求等行为的“块”,您可以使用它来模拟这些虚拟资源的推送和拉取。

将它们连接在一起和处理循环依赖关系的所有魔法都得到了照顾。

于 2013-04-03T12:24:46.740 回答
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)) {...}. 因此,每次收到消息时,接收者都会检查列表是否包含自身。如果不是,他发送消息,将自身添加到发件人列表中。

于 2013-04-03T12:43:21.793 回答
0

似乎你在正确的轨道上......它实际上是称为观察者/监听器设计模式......你应该使用 C# 中的事件来更好地实现该模式。事件基本上是一种委托,您可以在 MSDN 或 Google 中找到更多信息...

关于循环问题:

您只需将发件人列表与消息一起传递.. 并且每个对象都必须检查他是否是该列表中的发件人之一,并决定他是否应该发送梅西的天气。

于 2013-04-03T12:31:28.717 回答
0

我不认为代表是解决您提出的问题的好方法。让我们看一下以下场景:

ObjB 需要 1 个电力单位,现在,假设它有一个名为“GetElectricity”的委托,正如我从您所写的内容中了解的那样,PwrA、PwrB 都为委托添加了一个处理程序,PwrA 和 PwrB 处理程序都将被调用,或者您将尝试第一个处理程序,如果它没有提供所需的电力,它将尝试下一个处理程序……这将创建一个复杂、难以维护的软件。

你在说什么(或者至少,我会做什么:)),是事件,ObjB 将为 NeedElecricty 引发一个事件,所有 Pwr 对象都已注册它,如果它们可以提供电力,他们将调用一个事件“ProvideElectricity " 在 ObjB 上,ObjB 可以决定他将从其中哪一个获得他需要的电源,并通知他们他需要来自 PwrA 的 1 个电源单元(并会告诉 PwrB 他不需要它服务)。

寻找观察者和事件,因为这是您主要谈论的内容。


我同意@Clint,TPL 数据流是最好的解决方案,因为它完全符合您的要求。但正如你所说,它超出了范围。

于 2013-04-03T12:34:46.687 回答