I have an object like this:
public partial class CableApplication : StateObject
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public CableApplication()
{
this.CableProperties = new HashSet<CableProperty>();
}
public int Id { get; set; }
public int ProjectId { get; set; }
public string Application { get; set; }
public byte[] ts { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<CableProperty> CableProperties { get; set; }
public virtual Project Project { get; set; }
}
which is created in .edmx file automatically in database-first Visual Studio C# project. I want to export all the data of CableApplication into an XML file.
I wrote this code in the service:
public string ExportToXml<T>(T obj)
{
using (var stringwriter = new System.IO.StringWriter())
{
TextWriter writer = new StreamWriter(@"d:\\temp\\check.xml");
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stringwriter, obj);
writer.Close();
return stringwriter.ToString();
}
}
And this code in the frontend project:
private void exporToXMLToolStripMenuItem_Click(object sender, EventArgs e)
{
using (ICableService client = new CableService())
{
var applications = client.GetCableApplications(searchList.ToArray(), null, "").ToList(); // I get the list of cable Applications . works fine
var str = client.ExportToXml(applications);
}
}
But I get the following error:
Cannot serialize member 'Cable1Layer.Domain.CableApplication.CableProperties' of type 'System.Collections.Generic.ICollection`1[[Cable1Layer.Domain.CableProperty, Cable1Layer.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]', see inner exception for more details
There was an error reflecting type 'Cable1Layer.Domain.CableApplication'
How should I serialiaze this object?
The innermost error message (not shown in your question) is self explanatory:
XmlSerializercannot serialize interfaces because, not being concrete types, they cannot be constructed during deserialization. For more seeAs a workaround you could introduce a serializable surrogate property and mark the original property with
[XmlIgnore], however since your class was auto-generated from an .edmx file you probably don't want to modify any of the auto-generated code. Thus what you can do is:CableApplicationwas generated as a partial class to add a serializable surrogate property in a manually created partial file.XmlAttributeOverridesto suppress serialization of the non-serializable interface property.To do this, first extend
CablePropertiesas follows:Then add the following
XmlSerializerfactory:And finally modify
ExportToXml<T>(T obj)to use the serializer factory:Note that, when constructing serializer using
XmlAttributeOverrides, it is necessary to statically cache and reuse the serializer for reasons explained in Memory Leak using StreamReader and XmlSerializer.Demo fiddle here.