I have a class that is effectively a object based enum. There is a static set of objects exposed by the class, and everything uses these same instances. eg (Note the private constructor)
[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
}
This works great until I have to serialise across WCF. The DataContractSerializer
creates new objects by bypassing the constructor. This results in a valid FieldType
object, but it is a new instance that is not one of my static instances. This makes reference comparisons against the known static values fail.
Is there any way to override the serialisation behaviour for a class so that I create the object instance instead of populating an instance supplied to me?
Serializes and deserializes an instance of a type into an XML stream or document using a supplied data contract. This class cannot be inherited. The following example code shows a type named Person that is serialized by the DataContractSerializer.
One way to let the deserialization engine know about a type is by using the KnownTypeAttribute. The attribute cannot be applied to individual data members, only to whole data contract types. The attribute is applied to an outer type that can be a class or a structure.
To serialize a Business object marked with [ DataContract] and properties marked with [ DataMember] attributes… Then to deserialize back to your DataContract type, use this logic…
Whenever the outer type CompanyLogo2 is being deserialized, the deserialization engine knows about CircleType and TriangleType and, therefore, is able to find matching types for the "Circle" and "Triangle" data contracts.
I suspect you can do:
[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
}
Validated:
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
}
}
}
Note, however, that there seems little point serializing the Name
if we only use the Id
to identify the real object to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With