What is required is that it has a way to resolve members to numeric keys. This can take the form of inline attributes - for example, it allows [DataContract]
/[DataMember(Order=key)]
, [XmlType]
/[XmlElement(Order=key)]
, or [ProtoContract]
/[ProtoMember(key)]
.
There are also options via [DataContract]
to infer the contract alphabetically, but this is only safe if your contract type is not going to change in the future; to do this, add:
[ProtoContract(InferTagFromName = true)]
to the type (perhaps in a partial, see below). This applies directly to the scenario you present, where [DataMember]
indicates the members, but there is no defined Order
. Personally I prefer explicit layouts, for stability.
Another option doesn't even need hints like [DataMember]
; you can ask it to apply either BinaryFormatter
rules (all fields, public or private), or XmlSerializer
rules (public members, properties or fields); again, though, this is very unstable if your type changes!
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
But; another common scenario is that you have types coming from a generator, that you can't conveniently edit, since any edits would get lost at re-generation; for that scenario, partial
classes can be helpful. You can't add attributes to members via attributes, but [ProtoPartialMember]
can help here. For example, in a separate code file:
[ProtoContract]
[ProtoPartialMember(key, memberName)]
[ProtoPartialMember(anotherKey, anotherMemberName)]
...
public partial class Order {}
Sometimes, you have no access whatsoever to the type, so adding attributes of any kind is not an option. If your scenario is as you describe ([DataContract/
[DataMember], no
Order`), then a lazy option is to enable this globally:
Serializer.GlobalOptions.InferTagFromName = true;
or in v2:
RuntimeTypeModel.Default.InferTagFromNameDefault = true;
For more complex scenarios, v2 has a new MetaType
model devoted to this, where you can configure the layout at runtime:
RuntimeTypeModel.Default.Add(typeof(Order), false)
.Add(key, memberName).Add(anotherKey, anotherMemberName);
or if your keys are 1, 2, 3, ... then just:
RuntimeTypeModel.Default.Add(typeof(Order), false)
.Add(memberName, anotherMemberName, ...);
(there are a myriad of options on the MetaType
to control all aspects of the serialization)
I think that covers most of the options here!