需要的是它有办法将成员解析为数字键。这可以采用内联属性的形式——例如,它允许[DataContract]/[DataMember(Order=key)]、[XmlType]/[XmlElement(Order=key)]或[ProtoContract]/[ProtoMember(key)]。
还可以通过[DataContract] 选择按字母顺序推断合约,但这只有在您的合约类型将来不会改变时才是安全的;为此,请添加:
[ProtoContract(InferTagFromName = true)]
到类型(可能是部分,见下文)。这直接适用于您呈现的场景,其中[DataMember] 表示成员,但没有定义Order。为了稳定性,我个人更喜欢显式布局。
另一个选项甚至不需要像[DataMember] 这样的提示;您可以要求它应用BinaryFormatter 规则(所有字段,公共或私有)或XmlSerializer 规则(公共成员、属性或字段);但是,如果您的类型发生变化,这将非常不稳定!
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
但是;另一个常见的情况是你有来自生成器的类型,你不能方便地编辑,因为任何编辑都会在重新生成时丢失;对于那个场景,partial 类可能会有所帮助。您不能通过属性向成员添加属性,但[ProtoPartialMember] 可以在这里提供帮助。例如,在单独的代码文件中:
[ProtoContract]
[ProtoPartialMember(key, memberName)]
[ProtoPartialMember(anotherKey, anotherMemberName)]
...
public partial class Order {}
有时,您无权访问该类型whatsoever,因此添加任何类型的属性都不是一种选择。如果您的场景如您所描述的那样 ([DataContract/[DataMember], noOrder`),那么 lazy 选项是全局启用此功能:
Serializer.GlobalOptions.InferTagFromName = true;
或在 v2 中:
RuntimeTypeModel.Default.InferTagFromNameDefault = true;
对于更复杂的场景,v2 有一个新的 MetaType 模型专门用于此,您可以在运行时配置布局:
RuntimeTypeModel.Default.Add(typeof(Order), false)
.Add(key, memberName).Add(anotherKey, anotherMemberName);
或者如果你的键是 1, 2, 3, ... 那么只需:
RuntimeTypeModel.Default.Add(typeof(Order), false)
.Add(memberName, anotherMemberName, ...);
(MetaType 上有无数的选项来控制序列化的各个方面)
我认为涵盖了这里的大部分选项!