C#DataContract序列化,如何反序列化到已存在的实例

Ste*_*ger 8 c# serialization netdatacontractserializer

我有一个类,它包含所有现有实例的静态字典,这些实例是在编译时定义的.

基本上它看起来像这样:

[DataContract]
class Foo
{
  private static Dictionary<long, Foo> instances = new Dictionary<long, Foo>();

  [DataMember]
  private long id;

  public static readonly Foo A = Create(1);
  public static readonly Foo B = Create(2);
  public static readonly Foo C = Create(3);

  private static Foo Create(long id)
  {
    Foo instance = new Foo();
    instance.id = id;
    instances.Add(instance);
    return instance;
  }

  public static Foo Get(long id)
  {
    return instances[id];
  }    

}
Run Code Online (Sandbox Code Playgroud)

还有其他字段,派生类,但这对问题无关紧要.

只有id序列化.当反序列化此类型的实例时,我想获取已创建为静态字段(A,BC)的Foo.Get(id)实例,而不是获取新实例.

有一个简单的方法吗?我没有找到任何我能够理解的资源.

Mar*_*ell 17

在反序列化期间,它(AFAIK)总是使用一个新的对象(FormatterServices.GetUninitializedObject),但是为了让它反序列化之后替换对象(但在它们被返回给调用者之前),你可以实现IObjectReference,如下所示:

[DataContract]
class Foo : IObjectReference { // <===== implement an extra interface
    object IObjectReference.GetRealObject(StreamingContext ctx) {
        return Get(id);
    }
    ...snip
}
Run Code Online (Sandbox Code Playgroud)

完成...证明:

static class Program {
    static void Main() {
        Foo foo = Foo.Get(2), clone;
        DataContractSerializer ser = new DataContractSerializer(typeof(Foo));
        using (MemoryStream ms = new MemoryStream()) { // clone it via DCS
            ser.WriteObject(ms, foo);
            ms.Position = 0;
            clone = (Foo)ser.ReadObject(ms);
        }
        Console.WriteLine(ReferenceEquals(foo, clone)); // true
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,对于MSDN上的部分信任方案,此处有一些额外的注释.