What's the practical way of serializing an instance of subclass by using DataContractSerializer?
For example, here are the data types:
[DataContract]
public class Car
{
public Car()
{
Wheels = new Collection<Wheel>();
}
[DataMember]
public Collection<Wheel> Wheels { get; set; }
}
[DataContract]
public abstract class Wheel
{
[DataMember]
public string Name { get; set; }
}
[DataContract]
public class MichelinWheel : Wheel
{
[DataMember]
public string Wheel1Test { get; set; }
}
[DataContract]
public class BridgeStoneWheel : Wheel
{
[DataMember]
public string Wheel2Test { get; set; }
}
Then here is the code that creates a car with two differen wheels:
Car c开发者_如何学JAVAar = new Car();
MichelinWheel w1 = new MichelinWheel { Name = "o1", Wheel1Test = "o1 test" };
BridgeStoneWheel w2 = new BridgeStoneWheel { Name = "o2", Wheel2Test = "o2 test" };
car.Wheels.Add(w1);
car.Wheels.Add(w2);
Now if I try to serialize the car by using DataContractSerializer, I will get an exception that says MichelinWheel is not expected. And I have to modify the Wheel class like this to make it work:
[DataContract]
[KnownType(typeof(MichelinWheel))]
[KnownType(typeof(BridgeStoneWheel))]
public abstract class Wheel
{
[DataMember]
public string Name { get; set; }
}
But this approach is not practical, because I am not able to list all kinds of wheels before they are created. And changing the Wheel class every time after a new brand of wheel is created is also not practical, because they might by created in third-party code.
So, what is the practical approach of serializing an instance of a subclass when using DataContractSerializer?
Thanks
Check this article using DataContractResolver
from WCF 4. You can also use KnownTypeAttribute
with passing name of a method that will use reflection to get all types. Anyway service requires that all types are known before it starts.
There are several ways to make known types available to the service.
The simplest you have outlined above, but obviously this requires you to recompile when new types are added, and depending on your configuration can make it awkward to avoid circular dependencies.
You can also configure the KnownTypes:
- through the service configuration file (service restart only required),
- add them as service known types provided through a static method on the service interface which you could get through reflection as Ladislav Mrnka has indicated (you could probably reflect over all loaded assemblies and return all types that have the DataContact attribute on them as known types, but I couldn't find an example of that.)
- implement your own way of getting them (perhaps through some bespoke configuration elements in the config file or just through a text file)
精彩评论