In Assembly A:
[DataContract]
public class Base
{
[DataMember]
public string SomeText { get; set; }
}
In Assembly B:
internal class Helper
{
internal static Base Deserialize(string serializedInstanceOfTypeBase)
{
DataContractSerializer serializer = new DataContractSerializer(typeof (Base));
XmlReader reader = XmlReader.Create(new StringReader(serializedInstanceOfTypeBase));
return (Base)serializer.ReadObject(reader);
}
}
In Assembly C:
[DataContract]
public class Derived : Base
{
[DataMember]
public string SomeMoreText { get; set; }
}
If I serialize an instance of type Derived
and pass it to Helper.Deserialize()
method, it fails with the SerializationException
:
Error in line 1 position 2. Expecting element 'Base' from namespace 'http://schemas.datacontract.org/2004/07'.. Encountered 'Element' with name 'Derived', namespace 'http://schemas.datacontract.org/2004/07'.
How can I get rid of this issue?
I am aware of the KnownType
attribute, but at the time of coding in assembly A and B, I am absolutely not aware of its derived types. So I cannot use that solution.
Design of my product is more complex which I cannot post here entirely. Helper.Desrialize()
method just gets a string
argument. There is no way (at present at least) for assembly A or B, to know about derived types of Base
class, even at runtime.
Assembly B references assembly A. But A & B cannot reference assembly C.
I am using C# 4.0. It's ok if the solution you provide is NOT using DataContractSerializer
.
To use the DataContractSerializer, first create an instance of a class and an object appropriate to writing or reading the format; for example, an instance of the XmlDictionaryWriter. Then call the WriteObject method to persist the data.
The process forms a sequence of bytes into a logical object; this is called an encoding process. At runtime when WCF receives the logical message, it transforms them back into corresponding . Net objects. This process is called serialization.
This code constructs an instance of the DataContractSerializer that can be used only to serialize or deserialize instances of the Person class. DataContractSerializer dcs = new DataContractSerializer(typeof(Person)); // This can now be used to serialize/deserialize Person but not PurchaseOrder.
It looks like you need both:
Tell the deserializer not to check the type (use verifyObjectName
parameter):
return (Base)serializer.ReadObject(reader, false);
see details here: http://msdn.microsoft.com/en-us/library/ms573850%28v=vs.110%29.aspx
Do you know the types at runtime ? If so, a simple approach might be just:
List<Type> knownTypes = ...; // now that you know what to expect
DataContractSerializer serializer = new DataContractSerializer(
typeof(Base), knownTypes);
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