我有一个名为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的所有实例序列化。
我的问题是如何反序化这种安排。目前我做以下事情:
这在我看来很笨重,而且不容易扩展。我希望Meter工厂不需要在反序列化期间搜索Manager.Foos,因为将来Meter可能会从其他地方获取它对Foo实例的反应,而不仅仅是Manager。
这个反序列化问题是否有一个简单但灵活的替代解决方案,可以轻松地重建对象的引用?
答案 0 :(得分:4)
序列化很难:)
以不会弄乱格式的方式自动执行此操作非常痛苦。这里的一个常见技巧是使用中心映射在de / serialising时分配不相关的不透明键。您可以通过在构造函数中启用引用跟踪在DataContractSerializer中看到这一点。然后,此密钥用于检查现有对象作为替代。
就个人而言,当它获得复杂的IMO时,是时候使用预制的气雾发生器了;即使在专用库中,也有点挑战性。我使用的方法(protobuf-net)非常相似,但更难阅读(二进制密集输出等)。
答案 1 :(得分:0)
在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)以链接到&#34; Foos&#34;在Manager类中。
我还没有完全明白你想要什么,但从这个角度来看,你已经弄得一团糟:p
答案 2 :(得分:0)
感谢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;