2009-12-02 41 views
1

我有表示沿着服务器链消息流的示范方案:如何在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; 
    } 

} 

有许多更多的消息。每个服务器和消息类型启用()的逻辑略有不同,但国家是相似的,所以我想通过写更多的东西一样来封装它:

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不会让我以这种方式使用对象来保持我的状态。有没有其他一些方法可以避免定义重复的布尔组,为链中的每个服务器定义一组?

回答

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

由于上面写了我的答案,我已经了解到另一个解决方案,它更接近我最初看的对于。

要使用具有实例变量的对象,可以从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();