问题
In. Net you can mark a field as non serializable, and it will be skipped during serialization.
I'm looking for a simple method that will allow me to control in runtime whether a specific field should be serialized.
回答1:
You are referring to "mark a field as non serializable", so I assume you are using BinaryFormatter
and [NonSerialized]
. If so, the only way to do conditional serialization is by implementing ISerializable
and adding a similar constructor, and putting the logic in the GetObjectData
implementation. This is tedious and error prone, though. I would suggest looking at protobuf-net, which has simpler conditional serialization, using the standard patterns used by TypeDescriptor
and XmlSerializer
, but is still binary output (more efficient than BinaryFormatter
, actually). Specifically:
[ProtoContract]
public class SomeType {
[ProtoMember(1)]
public string Name {get;set;}
private bool ShouldSerializeName() {
// return true to serialize Name, false otherwise
}
}
This ShouldSerialize*
is a standard name-based convention - nothing specific to this serializer.
Here's the same via ISerializable
:
[Serializable]
public class SomeType : ISerializable
{
public SomeType() { }
public string Name { get; set; }
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
if (/* should serialize Name */) info.AddValue("Name", Name);
//... all other fields
}
protected SomeType(SerializationInfo info, StreamingContext context)
{
foreach (SerializationEntry entry in info)
{
switch (entry.Name)
{
case "Name": Name = (string)entry.Value; break;
//... all other fields
}
}
}
}
Lots more to maintain; in particular, you have to take responsibility for all members when using ISerializable
- however, if you just use protobuf-net you can handle each on a case-by-case basis.
Actually, you can mix-and-match too, i.e. if you are stuck with using BinaryFormatter
, you can still offload the work to protobuf-net, but it will change the format (so won't be compatible with old data). For example:
[Serializable, ProtoContract]
public class SomeType : ISerializable
{
public SomeType() { }
[ProtoMember(1)]
public string Name { get; set; }
private bool ShouldSerializeName() { /* condition */ }
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
Serializer.Serialize(info, this);
}
protected SomeType(SerializationInfo info, StreamingContext context)
{
Serializer.Merge(info, this);
}
}
来源:https://stackoverflow.com/questions/11880666/net-serialization-how-to-selectively-ignore-data-fields