参考文献涉及C#时的序列化和反序列化

时间:2011-07-01 11:09:09

标签: c# design-patterns serialization

我有一个名为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.Foos
  • 反序列化包含MyFoo属性的Foo实例的仪表实例
  • Search Manager.Foos并找到MyMeter.MyFoo的匹配参考,然后从Manager.Foos中分配参考。

这在我看来很笨重,而且不容易扩展。我希望Meter工厂不需要在反序列化期间搜索Manager.Foos,因为将来Meter可能会从其他地方获取它对Foo实例的反应,而不仅仅是Manager。

这个反序列化问题是否有一个简单但灵活的替代解决方案,可以轻松地重建对象的引用?

3 个答案:

答案 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;