设计模式-C#中涉及引用时的序列化和反序列化
本文关键字:序列化 反序列化 引用 -C# 设计模式 | 更新日期: 2023-09-27 18:00:56
我有一个名为Manager的单例类,它包含一个对象实例列表:
static class Manager
{
static List<Foo> Foos = new List<Foo>();
}
然后,我有一个使用名为Meter的类的对象实例集合,该类使用对Foos:列表中项目的引用
class Meter
{
public Foo MyFoo = null;
}
...
public void CreateMeter(int UserChoice)
{
Meter MyMeter = new Meter();
MyMeter.MyFoo = Manager.Foos[UserChoice];
}
当应用程序保存项目文件时,它会序列化Foo中的Foo实例以及Meter的所有实例。
我的问题是如何反序列化这种安排。目前我做以下工作:
- 反序列化Foo的项目范围实例以重建Manager.FFoos
- 反序列化包含MyFoo属性的Foo实例的仪表实例
- 搜索Manager.Fos并找到MyMeter.MyFoo的匹配引用,然后从Manager.Foos分配引用
在我看来,这似乎很笨拙,而且不太容易扩展。我宁愿Meter工厂在反序列化过程中不需要搜索Manager.Fos,因为将来Meter可能会从其他地方引用Foo实例,而不仅仅是Manager。
对于这个反序列化问题,是否有一个简单但灵活的替代解决方案,可以轻松地重建对对象的引用?
串行化很难:(
以一种不会打乱格式的方式自动完成这项工作是一件痛苦的事。这里的一个常见技巧是,在去串行化/串行化时,使用中心映射来分配一个不相关的不透明密钥。通过在构造函数中启用引用跟踪,可以在DataContractSerializer中看到这一点。然后,该键用于检查现有对象作为替代项。
就我个人而言,当IMO变得如此复杂时,是时候使用预先罐装的空气呼吸器了;即使在一个专门的图书馆里,这也有点挑战性。我使用的方法(protobuf-net(非常相似,但更难阅读(二进制密集输出等(。
在Manager类中添加
public static ulong IdProvider=0
在Foo类中添加
public ulong MyId
在Foo ctor中添加
MyId=Manager.IdProvider++;
每个Foo类都将有一个唯一的id(最多2^64-1个实例(,只需保存IdProvider,就可以在重建时继续添加唯一的id。
您可能需要考虑更改Meter类以保存Foo的唯一id,并提供一个属性(get;set(来链接到Manager类中的"Foo"。
我还没有完全理解你想要什么,但从这个角度来看,你已经把事情搞得一团糟:p
感谢Marc和其他人的建议。基于Marc的关键思想和Henk的对象id生成器,这里是我迄今为止所拥有的。
Foo定义了一个包含唯一Guid的Guid属性。这是在构造函数中生成的,但也可以通过序列化/反序列化来保存/还原。
class Foo
{
public Guid TheGuid = Guid.NewGuid();
}
Meter不再使用引用,而是使用Guid:
class Meter
{
public Guid FooGuid;
}
创建仪表时,Guid建立连接:
public void CreateMeter(int UserChoice)
{
Meter MyMeter = new Meter();
MyMeter.FooGuid = Manager.Foos[UserChoice].TheGuid;
}
当Meter被序列化/反序列化时,Guid被存储/加载。
一个缺点是需要访问与仪表关联的Foo实例。必须执行查找,而不是直接使用引用,这将导致性能打击:
class Manager
{
public List<Foo> Foos = new List<Foo>();
public Foo GetFooFromGuid(Guid SearchGuid)
{
// search Foos and return instance with Guid == SearchGuid
}
}
这种方法的一个好处是,现在我可以创建一个委托,并有多个Foo源与电表关联:
Func<Guid, Foo> FooSource;
FooSource ManagerFooSource = Manager.GetFooFromGuid;