如何持久化实现状态模式的对象?

MHO*_*OOS 10 c# state design-patterns software-design state-machine

我是状态设计模式的新手,我找不到将对象的不同状态保存到数据库的正确示例(在我的例子中是SQL Server).该场景与下一篇文章中描述的示例非常相似[几乎相同],但是我没有找到将状态持久保存到数据库的适用解决方案.你们可以推荐一个链接或者可能举个例子吗?

C#中的状态模式用法和示例

另外:如何在运行时枚举所有不同的ConcreteState类型?举例来说,如果你有10个不同的国家,你声明与10个不同成员的EnumStates,并给每一个成员的ConcreteState关联EnumStates成员,或者你通过得到的ConcreteState的子类得到所有的不同的状态?

为了您的信息,我需要能够根据不同的状态搜索实体.

Dav*_*uth 7

国家实体本身没有国家,所以你需要保存的只是每个国家的身份.将State类名保存在数据库中并不是一个好主意,因为如果更改了State类名,则必须更改数据库.代替,

  • 为每个State类提供一个Enum值,该值对于该州是唯一的.
  • 当您持有具有State的对象时,请保留Enum.

要在加载对象时返回状态,也可以

  • 立即实例化对象的State成员并将其分配给对象的State成员,或
  • 如果实例化一个State是很昂贵的,那么通过一个方法更改对象以访问State成员,并根据State Identity Enum成员的值懒惰地实例化该方法中的State.

无论哪种方式,您都需要能够从Enum值转到State.通过遍历所有相关的State类来执行此操作,直到找到其标识值匹配的类.

那么,相关国家是什么?这取决于谁在写国家课程.

  • 在简单的情况下,您控制整个程序并且程序中的所有State类都是State-having对象的潜在成员,您可以循环遍历State超类或接口的所有子类或实现者,如下所示:获取实现接口的所有类型.

  • 如果由于某种原因存在您不想循环的状态类,只需在一个常量中定义一个您想要循环的列表,或者在配置中定义(如果您想更改它而不更改代码) .

如果使您的状态类列表很慢,只需在程序启动或首次使用时执行一次.如果您对列表进行硬编码,请不要在具有State的类中(它应该独立于特定的状态)或State超类(这会引入循环依赖); 将列表放在你的程序中更高(依赖性)或(如Farhad所建议的)在它自己的类中.

有很多例子说明如何使用State来保持对象 ; 这一个相对简单.


jga*_*fin 5

不要尝试将状态转换为表中的列,这是行不通的。

而是使用 JSON.NET 序列化状态,因为它支持继承。然后将它存储在一个表中,如:

create table OrderStates
(
    OrderId int not null,
    Data nvarchar(MAX) not null
);
Run Code Online (Sandbox Code Playgroud)

如果需要,可以包含更多列,但仅包含用于标识状态用途所需的列。

要在 JSON.NET 中激活继承支持,您必须使用:

var json = JsonConvert.SerializeObject(yourState, typeof(StateBaseClass), JsonConvert.DefaultSettings)`. 
using (var cmd = sqlConnection.CreateCommand())
{
    cmd.CommandText = "INSERT INTO OrderStates (OrderId, Data) VALUES(@OrderId, @Data)";
    cmd.Parameters.AddWithValue("OrderId", orderId);
    cmd.Parameters.AddWithValue("Data", json);
    cmd.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)

反序列化时也是如此,使用时指定基类JsonConvert.DeserializeObject()

如何在运行时枚举所有不同的 ConcreteState 类型?例如,如果您有 10 个不同的状态,您是声明一个具有 10 个不同成员的 EnumStates 并为每个 ConcreteState 成员指定一个关联的 EnumStates 成员,还是通过获取 ConcreteState 的子类来获取所有不同的状态?

子类。这是能够引入新状态或删除旧状态而无需修改其他类的唯一方法。对现有类的每次修改都会引入错误。