DataContractSerializer 和不可变类型.反序列化为已知对象实例
本文关键字:对象 实例 反序列化 不可变 类型 DataContractSerializer | 更新日期: 2023-09-27 18:30:48
我有一个类,它实际上是一个基于对象的枚举。类公开了一组静态对象,并且所有对象都使用这些相同的实例。例如(注意私有构造函数)
[DataContract]
public class FieldType
{
public static readonly FieldType Default = new FieldType(1, "Default");
public static readonly FieldType Name = new FieldType(2, "Name");
public static readonly FieldType Etc = new FieldType(3, "Etc");
private FieldType(uint id, string name)
{
Id = id;
Name = name;
}
[DataMember] public uint Id { get; private set; }
[DataMember] public string Name { get; private set; }
//snip other properties
}
这很好用,直到我必须跨 WCF 序列化。DataContractSerializer
通过绕过构造函数来创建新对象。这将生成一个有效的 FieldType
对象,但它是一个不是我的静态实例之一的新实例。这使得与已知静态值的引用比较失败。
有没有办法覆盖类的序列化行为,以便我创建对象实例而不是填充提供给我的实例?
我怀疑你可以做到:
[DataContract]
public class FieldType : IObjectReference
{
object IObjectReference.GetRealObject(StreamingContext ctx)
switch(Id) {
case 1: return Default;
case 2: return Name; // note this is a collision between static/non-static
case 3: return Etc;
default: throw new InvalidOperationException();
}
}
public static readonly FieldType Default = new FieldType(1, "Default");
// note this is a collision between static/non-static
public static readonly FieldType Name = new FieldType(2, "Name");
public static readonly FieldType Etc = new FieldType(3, "Etc");
private FieldType(uint id, string name)
{
Id = id;
Name = name; // note this is a collision between static/non-static
}
[DataMember] public uint Id { get; private set; }
// note this is a collision between static/non-static
[DataMember] public string Name { get; private set; }
//snip other properties
}
验证:
public static class Program
{
static void Main()
{
var obj = FieldType.Default;
using(var ms = new MemoryStream())
{
var ser = new DataContractSerializer(typeof (FieldType));
ser.WriteObject(ms, obj);
ms.Position = 0;
var obj2 = ser.ReadObject(ms);
bool pass = ReferenceEquals(obj, obj2); // true
}
}
}
但是请注意,如果我们只使用Id
来标识要使用的实际对象,那么序列化Name
似乎没有什么意义。
我建议您覆盖Equals
和GetHashcode
(以及==
和!=
),以便静态对象与WCF创建的对象的相等性检查有效。
数据传输对象 (DTO) 不适用于面向对象的行为,它们纯粹是状态类。但我能理解你面临的问题。
或者,使用不同的 DTO 在域对象与上述类一起工作时发送数据。