DataContractSerializer doesn't call my constructor? - c#

I just realized something crazy, which I assumed to be completely impossible : when deserializing an object, the DataContractSerializer doesn't call the constructor !
Take this class, for instance :
[DataContract]
public class Book
{
public Book()
{ // breakpoint here
}
[DataMember(Order = 0)]
public string Title { get; set; }
[DataMember(Order = 1)]
public string Author { get; set; }
[DataMember(Order = 2)]
public string Summary { get; set; }
}
When I deserialize an object of that class, the breakpoint is not hit. I have absolutely no idea how it is possible, since it is the only constructor for this object !
I assumed that perhaps an additional constructor was generated by the compiler because of the DataContract attribute, but I couldn't find it through reflection...
So, what I'd like to know is this : how could an instance of my class be created without the constructor being called ??
NOTE: I know that I can use the OnDeserializing attribute to initialize my object when deserialization begins, this is not the subject of my question.

DataContractSerializer (like BinaryFormatter) doesn't use any constructor. It creates the object as empty memory.
For example:
Type type = typeof(Customer);
object obj = System.Runtime.Serialization.
FormatterServices.GetUninitializedObject(type);
The assumption is that the deserialization process (or callbacks if necessary) will fully initialize it.

There are some scenario's that wouldn’t be possible without this behavior. Think of the following:
1) You have an object that has one constructor that sets the new instance to an "initialized" state. Then some methods are called on that instance, that bring it in a "processed" state. You don’t want to create new objects having the "processed" state, but you still want de serialize / deserialize the instance.
2) You created a class with a private constructor and some static properties to control a small set of allowed constructor parameters. Now you can still serialize / deserialize them.
XmlSerializer has the behavior you expected. I have had a some problems with the XmlSerializer because it DOES need a default constructor. Related to that, sometimes it makes sense to have private property setters. But the XmlSerializer also needs public getter and setter on properties in order to serialize / deserialize.
I think of the DataContractSerializer / BinaryFormatter behavior like suspending the state of an instance during serialization and resuming during deserialization. In other words, the instances are not “constructed” but “restored” to an earlier state.
As you already mentioned, the [OnDeserializing] attribute makes it possible to keep non serialized data in sync.

FWIW, you can call the constructor explicitly from a [OnDeserializing] method:
[OnDeserializing]
public void OnDeserializing(StreamingContext context)
{
this.GetType().GetConstructor(System.Array.Empty<Type>()).Invoke(this, null);
}

Use [OnDeserialized] attribute to initialise your properties.
// This method is called after the object
// is completely deserialized. Use it instead of the
// constructror.
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
fullName = firstName + " " + lastName;
}
Please refer to microsoft guid-lines:
https://learn.microsoft.com/en-us/dotnet/standard/serialization/serialization-guidelines

In my case, i wanted to create an object to use in a lock-clause. I tried implementing IDeserializationCallback (didn't work because callback only runs after properties have been assigned), [OnDeserialized] (didn't work, same previous reason), and ISerializable (didn't work because the class is decorated with the [DataContractAttribute]).
My workaround was to initialize the field before it's used using Interlocked.CompareExchange. A bit of unnecessary work gets done, but at least now my field gets initialized when a DataContractSerializer creates it.
Interlocked.CompareExchange(ref _sync, new object(), null);

Related

Json.NET public Activity properties not serialized

I was working on an enhancement in my Xamarin Android app to make working with Android's saved state easier. One part of the implementation for this needs to Json serialize the properties of current Activity class that have the custom [SaveState] attribute. All other properties are ignored. I've got this mechanism working using a POCO (and Json.NET as serializer). When defining a public property with the custom [SaveState] attribute, it serializes (only) that property as desired.
When I define a class that extends the (obviously) required Activity class, lets call it ExampleActivity, it doesn't serialize the public property anymore. So, the same setup that was working for the POCO isn't working anymore when extending the Activity.
In addition: it's not serializing anything of the ExampleActivity or of the inherited Activity's properties. Even though many are public. Just an empty Json string object.
When I add the [JsonProperty] attribute to the public property it d̲o̲e̲s̲ though! So I believe it's not a matter that Json.NET can't serialize the property, it just won't. For some reason it's ignoring it and everything else.
I've tried some things, but I can't seem to figure out why it's ignoring the properties. I've added a TraceWriter to the serializer in the hopes to see something that might point me in the right direction, but it doesn't.
I've added a small stripped code snippet that reproduces the issue:
public static class Example
{
public static void Run()
{
var exampleActivity = new ExampleActivity { PropertyA = "A value", PropertyB = "B value" };
// Default serializer settings with a memory trace writer
var serializerSettings = new JsonSerializerSettings { TraceWriter = new MemoryTraceWriter() };
var serializedString = JsonConvert.SerializeObject(exampleActivity, serializerSettings);
System.Diagnostics.Debug.WriteLine(serializerSettings.TraceWriter);
// NOTE: The serialized string only contains PropertyB
System.Diagnostics.Debug.WriteLine($"SerializedString: {serializedString}");
}
public class ExampleActivity : Activity
{
//[JsonProperty]
public string PropertyA { get; set; }
[JsonProperty]
public string PropertyB { get; set; }
}
}
When calling the static Example.Run() you'll see that even though the ExampleActivity's PropertyA is a regular public property it's not serialized. Whereas the PropertyB which has the [JsonProperty] attribute i̲s̲ serialized.
For my solution I don't want to be adding the [JsonProperty] attribute to each property that also get's the custom [SaveState] attribute. That it's currently using Json (de)serializing behind the scenes to achieve the desired behavior shouldn't have influence on the usage of the [SaveState] behavior.
I hope I've been sufficiently complete in the describing of my issue. Does anybody know why the regular public properties of the class extending the Activity aren't serialized? And/or how to fix this?

XMLDeserialize, "There was an error reflecting type" [duplicate]

Using C# .NET 2.0, I have a composite data class that does have the [Serializable] attribute on it. I am creating an XMLSerializer class and passing that into the constructor:
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
I am getting an exception saying:
There was an error reflecting type.
Inside the data class there is another composite object. Does this also need to have the [Serializable] attribute, or by having it on the top object, does it recursively apply it to all objects inside?
Look at the inner exception that you are getting. It will tell you which field/property it is having trouble serializing.
You can exclude fields/properties from xml serialization by decorating them with the [XmlIgnore] attribute.
XmlSerializer does not use the [Serializable] attribute, so I doubt that is the problem.
Remember that serialized classes must have default (i.e. parameterless) constructors. If you have no constructor at all, that's fine; but if you have a constructor with a parameter, you'll need to add the default one too.
I had a similar problem, and it turned out that the serializer could not distinguish between 2 classes I had with the same name (one was a subclass of the other). The inner exception looked like this:
'Types BaseNamespace.Class1' and 'BaseNamespace.SubNamespace.Class1' both use the XML type name, 'Class1', from namespace ''. Use XML attributes to specify a unique XML name and/or namespace for the type.
Where BaseNamespace.SubNamespace.Class1 is a subclass of BaseNamespace.Class1.
What I needed to do was add an attribute to one of the classes (I added to the base class):
[XmlType("BaseNamespace.Class1")]
Note: If you have more layers of classes you need to add an attribute to them as well.
Most common reasons by me:
- the object being serialized has no parameterless constructor
- the object contains Dictionary
- the object has some public Interface members
Also be aware that XmlSerializer cannot serialize abstract properties.. See my question here (which I have added the solution code to)..
XML Serialization and Inherited Types
All the objects in the serialization graph have to be serializable.
Since XMLSerializer is a blackbox, check these links if you want to debug further into the serialization process..
Changing where XmlSerializer Outputs Temporary Assemblies
HOW TO: Debug into a .NET XmlSerializer Generated Assembly
If you need to handle specific attributes (i.e. Dictionary, or any class), you can implement the IXmlSerialiable interface, which will allow you more freedom at the cost of more verbose coding.
public class NetService : IXmlSerializable
{
#region Data
public string Identifier = String.Empty;
public string Name = String.Empty;
public IPAddress Address = IPAddress.None;
public int Port = 7777;
#endregion
#region IXmlSerializable Implementation
public XmlSchema GetSchema() { return (null); }
public void ReadXml(XmlReader reader)
{
// Attributes
Identifier = reader[XML_IDENTIFIER];
if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
}
public void WriteXml(XmlWriter writer)
{
// Attributes
writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
}
private const string XML_IDENTIFIER = "Id";
private const string XML_NETWORK_ADDR = "Address";
private const string XML_NETWORK_PORT = "Port";
#endregion
}
There is an interesting article, which show an elegant way to implements a sophisticated way to "extend" the XmlSerializer.
The article say:
IXmlSerializable is covered in the official documentation, but the documentation states it's not intended for public use and provides no information beyond that. This indicates that the development team wanted to reserve the right to modify, disable, or even completely remove this extensibility hook down the road. However, as long as you're willing to accept this uncertainty and deal with possible changes in the future, there's no reason whatsoever you can't take advantage of it.
Because this, I suggest to implement you're own IXmlSerializable classes, in order to avoid too much complicated implementations.
...it could be straightforward to implements our custom XmlSerializer class using reflection.
I just got the same error and discovered that a property of type IEnumerable<SomeClass> was the problem. It appears that IEnumerable cannot be serialized directly.
Instead, one could use List<SomeClass>.
I've discovered that the Dictionary class in .Net 2.0 is not serializable using XML, but serializes well when binary serialization is used.
I found a work around here.
I recently got this in a web reference partial class when adding a new property. The auto generated class was adding the following attributes.
[System.Xml.Serialization.XmlElementAttribute(Order = XX)]
I needed to add a similar attribute with an order one higher than the last in the auto generated sequence and this fixed it for me.
I too thought that the Serializable attribute had to be on the object but unless I'm being a complete noob (I am in the middle of a late night coding session) the following works from the SnippetCompiler:
using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;
public class Inner
{
private string _AnotherStringProperty;
public string AnotherStringProperty
{
get { return _AnotherStringProperty; }
set { _AnotherStringProperty = value; }
}
}
public class DataClass
{
private string _StringProperty;
public string StringProperty
{
get { return _StringProperty; }
set{ _StringProperty = value; }
}
private Inner _InnerObject;
public Inner InnerObject
{
get { return _InnerObject; }
set { _InnerObject = value; }
}
}
public class MyClass
{
public static void Main()
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
TextWriter writer = new StreamWriter(#"c:\tmp\dataClass.xml");
DataClass clazz = new DataClass();
Inner inner = new Inner();
inner.AnotherStringProperty = "Foo2";
clazz.InnerObject = inner;
clazz.StringProperty = "foo";
serializer.Serialize(writer, clazz);
}
finally
{
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
}
I would imagine that the XmlSerializer is using reflection over the public properties.
Sometime, this type of error is because you dont have constructur of class without argument
I had a situation where the Order was the same for two elements in a row
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]
.... some code ...
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]
When I changed the code to increment the order by one for each new Property in the class, the error went away.
I was getting the same error when I created a property having a datatype - Type. On this, I was getting an error - There was an error reflecting type. I kept checking the 'InnerException' of every exception from the debug dock and got the specific field name (which was Type) in my case. The solution is as follows:
[XmlIgnore]
public Type Type { get; set; }
Also note that you cannot serialize user interface controls and that any object you want to pass onto the clipboard must be serializable otherwise it cannot be passed across to other processes.
I have been using the NetDataSerialiser class to serialise
my domain classes. NetDataContractSerializer Class.
The domain classes are shared between client and server.
I had the same issue and in my case the object had a ReadOnlyCollection. A collection must implement Add method to be serializable.
I have a slightly different solution to all described here so far, so for any future civilisation here's mine!
I had declared a datatype of "time" as the original type was a TimeSpan and subsequently changed to a String:
[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]
however the actual type was a string
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
by removing the DateType property the Xml can be serialized
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
Or
[XmlIgnore]
string [] strFielsName {get;set;}

Immutability and XML Serialization

I have several classes that are immutable once their initial values are set. Eric Lippert calls this write-once immutability.
Implementing write-once immutability in C# usually means setting the initial values via the constructor. These values initialize readonly fields.
But if you need to serialize a class like this to XML, using either the XmlSerializer or the DataContractSerializer, you must have a parameterless constructor.
Does anyone have suggestions for how to work around this problem? Are there other forms of immutability that work better with serialization?
EDIT: As #Todd pointed out, the DataContractSerializer does not require a parameterless constructor. According to the DataContractSerializer documentation on MSDN, DataContractSerializer "does not call the constructor of the target object."
Assuming this is your "immutable" object :
public class Immutable
{
public Immutable(string foo, int bar)
{
this.Foo = foo;
this.Bar = bar;
}
public string Foo { get; private set; }
public int Bar { get; private set; }
}
You can create a dummy class to represent that immutable object during serialization/deserialization :
public class DummyImmutable
{
public DummyImmutable(Immutable i)
{
this.Foo = i.Foo;
this.Bar = i.Bar;
}
public string Foo { get; set; }
public int Bar { get; set; }
public Immutable GetImmutable()
{
return new Immutable(this.Foo, this.Bar);
}
}
When you have a property of type Immutable, don't serialize it, and instead serialize a DummyImmutable :
[XmlIgnore]
public Immutable SomeProperty { get; set; }
[XmlElement("SomeProperty")]
public DummyImmutable SomePropertyXml
{
get { return new DummyImmutable(this.SomeProperty); }
set { this.SomeProperty = value != null ? value.GetImmutable() : null; }
}
OK, this is a bit long for something that looks so simple... but it should work ;)
If the class is truly immutable, just use public readonly fields marked with attributes.
[DataContract()]
public class Immutable
{
[DataMember(IsRequired=true)]
public readonly string Member;
public Immutable(string member)
{
Member = member;
}
}
"Realio-trulio" immutability involves the constructor. Popsicle immutability is where you can do, for example:
Person p = new Person();
p.Name = "Fred";
p.DateOfBirth = DateTime.Today;
p.Freeze(); // **now** immutable (edit attempts throw an exception)
(or the same with an object initializer)
This fits DataContractSerializer quite well, as long as you handle to on-serialized callback to do the Freeze. XmlSerializer doesn't do serialization callbacks, so is more work.
Either would suit if you use custom serialization (IXmlSerializable), though. Likewise, custom serialization is broadly doable with realio-trulio immutability, but is painful - and it is a bit of a lie, as it is "create once, then call interface method" - so not really properly immutable.
For true immutability, use a DTO.
I recommend taking a look at the discussion here: Why XML-Serializable class need a parameterless constructor.
You should consider using DataContractSerializer. As far as I can tell from the docs, this do not require a parameterless constructor, and can serialize/deserialize private members.
I just had a look at the article you linked to. In his terminology, objects using readonly fields initialized in the constructor are called "write-only immutability".
"Popsicle immutability" is a bit different. Lippert gives two examples of where it would be useful: deserialization (the problem which you are trying to solve), and circular references where A and B need to be created independently but A needs have a reference to B, and B a reference to A.
The two more obvious ways to achieve this result have been mentioned here (as I was writing this, in fact). The pattern Thomas Levesque mentions is basically the "Builder" pattern. But it's rather unwieldly in this case because you need to not only go from Builder to Immutable, but also from Immutable to Builder so that the serialization/deserialization is symmetrical.
So the "lock" pattern, as mentioned by Marc Gravell, seems more useful. I'm not familiar with C# though, so I'm not sure how best to implement it. I guess probably a private property such as locked. Then all the getter methods need to explicitly check whether the object is locked (aka "frozen") yet. If so they should throw an exception (it's a runtime error; you cannot enforce popstick immutability at compile time).

Why isn't my public property serialized by the XmlSerializer?

This is one i struggled with for ages so thought I'd document somewhere. (Apologies for asking and answering a question.)
(C# .net 2.0)
I had a class that was being serialized by XmlSerializer, I added a new public property however it wasn't being included in the output XML.
It's not mentioned in the docs anywhere I could find, but public properties must have a set as well as a get to be serialized! I guess this is because it assumes that if you're going to serialize then you'll want to deserialize from the same file, so only serializes properties that have both a set and a get.
As mentioned, most properties must have both a getter and setter; the main exception to this is lists - for example:
private readonly List<Foo> bar = new List<Foo>();
public List<Foo> Bar {get { return bar; } } // works fine
which will work fine; however, if XmlSerializer finds a setter - it demands that it is public; the following will not work:
public List<Foo> Bar {get; private set;} // FAIL
Other reasons it might not serialize:
it isn't public with get and set (or is readonly for a field)
it has a [DefaultValue] attribute, and is with that value
it has a public bool ShouldSerializeFoo() method that returned false
it has a public bool FooSpecified {get;set;} property or field that returned false
it is marked [XmlIgnore]
it is marked [Obsolete]
Any of these will cause it not to serialize
The point about getter+setter is made in the 3rd paragraph on the "Intro to Xml Serialization" page. It's actually in a call-out box. Can't miss it!
Intro-to-XML Serialization http://www.freeimagehosting.net/uploads/2f04fea2db.png
(having a little too much fun with Freeimagehosting.net)
Also properties that return null are not serialized!
if you don't want to implement proper Setters (because maybe you are neither wanting to deserialize or change an objects value) you can just use dummy setters like this set { }, so that the XMLSerializer works, but nothing happens if you use the Setter...
i.E.
public string ID { get { return _item.ID.ToString(); } set { } }
And if your class inherits a list and also has its own members, only the elements of the list get serialized. The data present in your class members is not captured.
Took some time figuring out this!
One more thing to add about serialization of collections:
The XmlSerializer ignores collections of interfaces!
And by that I mean ignore. While you will get an exception for a line like:
public IFoo Foo { get; set; }
you will not get an exception for:
public ICollection<IFoo> LotsOfFoos { get { return this.fooBackingField; } }
You can implement the IXmlSerializer and do the serialization manually, and benefit from serializing properties, and vice versa, deserializing them using constructors / private field assignment.

XmlSerializer - There was an error reflecting type

Using C# .NET 2.0, I have a composite data class that does have the [Serializable] attribute on it. I am creating an XMLSerializer class and passing that into the constructor:
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
I am getting an exception saying:
There was an error reflecting type.
Inside the data class there is another composite object. Does this also need to have the [Serializable] attribute, or by having it on the top object, does it recursively apply it to all objects inside?
Look at the inner exception that you are getting. It will tell you which field/property it is having trouble serializing.
You can exclude fields/properties from xml serialization by decorating them with the [XmlIgnore] attribute.
XmlSerializer does not use the [Serializable] attribute, so I doubt that is the problem.
Remember that serialized classes must have default (i.e. parameterless) constructors. If you have no constructor at all, that's fine; but if you have a constructor with a parameter, you'll need to add the default one too.
I had a similar problem, and it turned out that the serializer could not distinguish between 2 classes I had with the same name (one was a subclass of the other). The inner exception looked like this:
'Types BaseNamespace.Class1' and 'BaseNamespace.SubNamespace.Class1' both use the XML type name, 'Class1', from namespace ''. Use XML attributes to specify a unique XML name and/or namespace for the type.
Where BaseNamespace.SubNamespace.Class1 is a subclass of BaseNamespace.Class1.
What I needed to do was add an attribute to one of the classes (I added to the base class):
[XmlType("BaseNamespace.Class1")]
Note: If you have more layers of classes you need to add an attribute to them as well.
Most common reasons by me:
- the object being serialized has no parameterless constructor
- the object contains Dictionary
- the object has some public Interface members
Also be aware that XmlSerializer cannot serialize abstract properties.. See my question here (which I have added the solution code to)..
XML Serialization and Inherited Types
All the objects in the serialization graph have to be serializable.
Since XMLSerializer is a blackbox, check these links if you want to debug further into the serialization process..
Changing where XmlSerializer Outputs Temporary Assemblies
HOW TO: Debug into a .NET XmlSerializer Generated Assembly
If you need to handle specific attributes (i.e. Dictionary, or any class), you can implement the IXmlSerialiable interface, which will allow you more freedom at the cost of more verbose coding.
public class NetService : IXmlSerializable
{
#region Data
public string Identifier = String.Empty;
public string Name = String.Empty;
public IPAddress Address = IPAddress.None;
public int Port = 7777;
#endregion
#region IXmlSerializable Implementation
public XmlSchema GetSchema() { return (null); }
public void ReadXml(XmlReader reader)
{
// Attributes
Identifier = reader[XML_IDENTIFIER];
if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
}
public void WriteXml(XmlWriter writer)
{
// Attributes
writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
}
private const string XML_IDENTIFIER = "Id";
private const string XML_NETWORK_ADDR = "Address";
private const string XML_NETWORK_PORT = "Port";
#endregion
}
There is an interesting article, which show an elegant way to implements a sophisticated way to "extend" the XmlSerializer.
The article say:
IXmlSerializable is covered in the official documentation, but the documentation states it's not intended for public use and provides no information beyond that. This indicates that the development team wanted to reserve the right to modify, disable, or even completely remove this extensibility hook down the road. However, as long as you're willing to accept this uncertainty and deal with possible changes in the future, there's no reason whatsoever you can't take advantage of it.
Because this, I suggest to implement you're own IXmlSerializable classes, in order to avoid too much complicated implementations.
...it could be straightforward to implements our custom XmlSerializer class using reflection.
I just got the same error and discovered that a property of type IEnumerable<SomeClass> was the problem. It appears that IEnumerable cannot be serialized directly.
Instead, one could use List<SomeClass>.
I've discovered that the Dictionary class in .Net 2.0 is not serializable using XML, but serializes well when binary serialization is used.
I found a work around here.
I recently got this in a web reference partial class when adding a new property. The auto generated class was adding the following attributes.
[System.Xml.Serialization.XmlElementAttribute(Order = XX)]
I needed to add a similar attribute with an order one higher than the last in the auto generated sequence and this fixed it for me.
I too thought that the Serializable attribute had to be on the object but unless I'm being a complete noob (I am in the middle of a late night coding session) the following works from the SnippetCompiler:
using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;
public class Inner
{
private string _AnotherStringProperty;
public string AnotherStringProperty
{
get { return _AnotherStringProperty; }
set { _AnotherStringProperty = value; }
}
}
public class DataClass
{
private string _StringProperty;
public string StringProperty
{
get { return _StringProperty; }
set{ _StringProperty = value; }
}
private Inner _InnerObject;
public Inner InnerObject
{
get { return _InnerObject; }
set { _InnerObject = value; }
}
}
public class MyClass
{
public static void Main()
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
TextWriter writer = new StreamWriter(#"c:\tmp\dataClass.xml");
DataClass clazz = new DataClass();
Inner inner = new Inner();
inner.AnotherStringProperty = "Foo2";
clazz.InnerObject = inner;
clazz.StringProperty = "foo";
serializer.Serialize(writer, clazz);
}
finally
{
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
}
I would imagine that the XmlSerializer is using reflection over the public properties.
Sometime, this type of error is because you dont have constructur of class without argument
I had a situation where the Order was the same for two elements in a row
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]
.... some code ...
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]
When I changed the code to increment the order by one for each new Property in the class, the error went away.
I was getting the same error when I created a property having a datatype - Type. On this, I was getting an error - There was an error reflecting type. I kept checking the 'InnerException' of every exception from the debug dock and got the specific field name (which was Type) in my case. The solution is as follows:
[XmlIgnore]
public Type Type { get; set; }
Also note that you cannot serialize user interface controls and that any object you want to pass onto the clipboard must be serializable otherwise it cannot be passed across to other processes.
I have been using the NetDataSerialiser class to serialise
my domain classes. NetDataContractSerializer Class.
The domain classes are shared between client and server.
I had the same issue and in my case the object had a ReadOnlyCollection. A collection must implement Add method to be serializable.
I have a slightly different solution to all described here so far, so for any future civilisation here's mine!
I had declared a datatype of "time" as the original type was a TimeSpan and subsequently changed to a String:
[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]
however the actual type was a string
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
by removing the DateType property the Xml can be serialized
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
Or
[XmlIgnore]
string [] strFielsName {get;set;}

Categories