如何在模型中封装状态变量?

时间:2009-12-02 17:32:27

标签: c# nmodel

我有一个模型程序,它代表一系列服务器上的消息流:

public class MyModel
{
    static bool x_send_msg1 = false; // has X sent msg1?
    static bool y_recv_msg1 = false; // has Y received msg1?

    static bool y_send_msg1 = false; // has Y sent msg1?
    static bool z_send_msg1 = false; // has Z received msg1?

    // (etc for more servers and more messages)

    [Action]
    static void YSendMsg1()
    {
       // Y sends Msg1 to Z
       y_send_msg1 = true;
       z_recv_msg1 = true;
    }
    static bool YSendMsg1Enabled()
    {
       // in the simplest case, this can happen whenever Y has received the
       // message but not yet forwarded it
       return y_recv_msg1 && !y_send_msg1;
    }

}

还有更多消息。每个服务器和消息类型的Enabled()逻辑略有不同,但状态类似,所以我想通过编写类似的东西来封装它:

class State
{
    public bool send_msg1 = false;
    public bool recv_msg1 = false;
}
public static State X = new State();
public static State Y = new State();

然后在我的操作中使用封装状态:

[Action]
static void YSendMsg1()
{
  // instead of y_qqq above, now we can write Y.qqq:
   Y.send_msg1 = true;
   Z.recv_msg1 = true;
}
static bool YSendMsg1Enabled()
{
   return Y.recv_msg1 && !Y.send_msg1;
}

然而,NModel不会让我以这种方式使用对象来保持我的状态。还有其他方法可以避免定义重复的布尔组,一个用于链中的每个服务器吗?

3 个答案:

答案 0 :(得分:2)

除了风格问题之外,如问题中所示封装状态的主要好处是减少必须编写和读取的代码量。而不必编写(#servers * #messages)声明,只需要(#server + #messages)。

通过使用NModel的内置Set类来跟踪每条消息的状态,可以实现相同的代码减少(相应的可读性改进和腕管综合症的减少)。名为send_msg1的集合包含已发送msg1的所有服务器的名称:

public class MyModel
{
    static set<int> send_msg1 = set<int>.EmptySet; // has server #n sent msg #1?
    static set<int> recv_msg1 = set<int>.EmptySet; // has server #n received msg #1?
    // (etc for more messages)

    static int X = 1;
    static int Y = 2;
    // (etc for more server names)

    [Action]
    static void YSendMsg1()
    {
       // Y sends Msg1 to Z
       send_msg1 = send_msg1.Add(Y);
       recv_msg1 = recv_msg1.Add(Z);
    }
    static bool YSendMsg1Enabled()
    {
       // in the simplest case, this can happen whenever Y has received the
       // message but not yet forwarded it
       return recv_msg1.Contains(Y) && !send_msg1.Contains(Y);
    }

}

(可以进一步减少代码事件的数量,例如通过使用集合映射来保存单个变量中的所有内容。但是,将状态保持分离的一个优点是它可以生成更清晰的状态摘要。模型查看器。)

答案 1 :(得分:1)

自从写上我的答案以来,我已经了解了另一种更接近我原本想要的解决方案。

要使用具有实例变量的对象,您可以从LabeledInstance派生,如下所示。应使用静态Create()方法分配实例,并且应使用重写的Initialize()方法初始化字段。

(您也可以使用实例方法进行操作,但为此,您必须为该类分配域;该域的名称应对应于包含该类的所有当前实例的静态集。)

在幕后,NModel将把这个类翻译成一堆地图,一个用于类中的每个实例变量。这些映射的关键是索引类名的实例,例如, State(1)。这在MVC工具中有点难以阅读,因此您可能还希望保留某种实例变量,其中包含对象状态的清晰,合并的摘要。

class State : LabeledInstance<State>
{ 
    public override void Initialize()
    {
        send_msg1 = false;
        recv_msg1 = false;
    }
    public bool send_msg1;
    public bool recv_msg1;
} 

public static State X = State.Create();
public static State Y = State.Create();

答案 2 :(得分:0)

我认为观察者模式可能会对您有所帮助 - http://www.dofactory.com/Patterns/PatternObserver.aspx