如何在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 不会让我以这种方式使用对象来保持我的状态。是否有其他方法可以避免定义重复的布尔值组,每个布尔值对应链中的每个服务器?
I have a model program that represents message flow along a chain of servers:
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;
}
}
There are lots more messages. The Enabled() logic for each server and message type is slightly different, but the state is similar, so I would like to encapsulate it by writing something more like:
class State
{
public bool send_msg1 = false;
public bool recv_msg1 = false;
}
public static State X = new State();
public static State Y = new State();
and then use the encapsulated state in my actions:
[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;
}
However NModel won't let me use objects in this fashion to hold my state. Is there some other way I can avoid defining repeating groups of booleans, one for each server in the chain?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
撇开风格问题不谈,问题中所示的封装状态的主要好处是减少必须编写和读取的代码量。不必编写 (#servers * #messages) 声明,只需 (#server + #messages)。
通过使用 NModel 的内置
Set
类来跟踪每条消息的状态,可以实现相同的代码减少(相应地提高可读性并减少腕管综合症)。名为send_msg1
的集合包含已发送msg1
的所有服务器的名称:(可以进一步减少代码事件的数量,例如通过使用设置将所有内容保存在单个变量中。但是,将状态空间分开的一个优点是它可以在模型查看器中生成更清晰的状态摘要。)
Questions of style aside, the main benefit of encapsulating the state as shown in the question is to reduce the amount of code that must be written and read. Instead of having to write (#servers * #messages) declarations, only (#server + #messages) are required.
The same reduction in code (with corresponding improvements in readability and reduction in carpal tunnel syndrome) can be achieved by using NModel's built-in
Set
class to track the state of each message. A set calledsend_msg1
contains the names of all the servers that have sentmsg1
:(It is possible to reduce the amount of code event further, for example by using a map of sets to hold everything in a single variable. However one advantage of leaving the state patially separated is that it produces more legible state summaries in the model viewer.)
自从在上面写下我的答案以来,我了解到了另一个更接近我最初寻找的解决方案。
要使用带有实例变量的对象,您可以从
LabeledInstance
派生,如下所示。应使用静态Create()
方法分配实例,并应在重写的Initialize()
方法中初始化字段。(您还可以对操作使用实例方法,但要做到这一点,您必须为类分配一个域;该域的名称应对应于包含该类的所有当前实例的静态集。)
在幕后,NModel 是将把这个类翻译成一堆映射,一个对应类中的每个实例变量。这些映射的键将是类名的索引实例,例如
State(1)
。这在 MVC 工具中可能有点难以阅读,因此您可能还希望保留某种实例变量,其中包含对象状态的清晰、统一的摘要。Since writing my answer above, I have learned of another solution that is closer to what I was originally looking for.
To use objects with instance variables, you can derive from
LabeledInstance
as shown below. The instances should be allocated using the staticCreate()
method, and fields should be initialized in an overriddenInitialize()
method.(You can also use instance methods for actions, but to do so you must assign a domain to the class; the name of that domain should correspond to a static set that contains all current instances of the class.)
Behind the scenes, NModel is going to translate this class into a bunch of maps, one for each instance variable in the class. The key into those maps will be indexed instances of the class name, e.g.
State(1)
. This can be somewhat hard to read within the MVC tool, so you may also want to keep some kind of instance variable that contains a legible, consolidated summary of the object's state.我认为观察者模式可能会在这里帮助你 - http://www.dofactory.com/Patterns/模式观察者.aspx
I think the observer pattern might help you here - http://www.dofactory.com/Patterns/PatternObserver.aspx