Cannot serialize member.... because it is an interface
In the code you posted, the type of CustomerAddresses
is IList<CustomerAdress>
. That's an interface. Like the error message says, you can't serialize an interface.
In some circumstances, one might not be interested in serializing ALL fields of an object. In that case, the C# syntax to explicitly exclude a field from the serialization of an object is the following:
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes{ XmlIgnore = true };
attrOverrides.Add(type, member, attrs); // "type" = type of the class that contains the member
XmlSerializer serializer = new XmlSerializer(obj.GetType(), attrOverrides);
[...]
For example, to exclude, e.g. for privacy reasons, the "Password" field from the serialization of an "obj" object we should write:
attrOverrides.Add(obj.GetType(), "Password", attrs);
For fields not declared directly in the object but inherited, the "type" parameter refers to the ancestor in which the field is declared. For example, to avoid, in an object that is a descendant of System.ComponentModel.Component, the error "Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface", the syntax to use is:
attrOverrides.Add(typeof(System.ComponentModel.Component), "Site", attrs);
In general, the XMLSerializer cannot serialize an object of a class that exposes interface-type fields. Nevertheless, if someone still wants to serialize (with XMLSerializer) an object of this type (e.g. for log reasons) and has no problem ignoring fields of the interface type in serialization, the following function automatically ignores fields of this type (NB: of course the final result will NOT be the serialization of the initial object, but the serialization EXCLUDING the ignored parts, which is not the same thing):
public static string Serialize<T>(T obj, bool ignoreInterfaceTypeFields = false, List<Tuple<Type, string>> ignoreTypeList = null)
{
string retValue = string.Empty;
try
{
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes{ XmlIgnore = true };
ignoreTypeList?.ForEach(t => attrOverrides.Add(t.Item1, t.Item2, attrs)); // ignore fields in ignoreTypeList
if (ignoreInterfaceTypeFields)
{
foreach (var t in obj.GetType().GetProperties())
{
if (t.PropertyType.IsInterface)
if (attrOverrides[t.DeclaringType, t.Name] is null)
attrOverrides.Add(t.DeclaringType, t.Name, attrs); // ignore interface type fields
}
}
XmlSerializer serializer = new XmlSerializer(obj.GetType(), attrOverrides);
using (var sw = new StringWriter())
{
using (XmlTextWriter writer = new XmlTextWriter(sw) { Formatting = Formatting.Indented })
{
serializer.Serialize(writer, obj);
retValue = sw.ToString();
}
}
}
catch (Exception ex) { throw ex; }
return retValue;
}
// declared in non-generic, non-nested static classes
public static string Serialize<T>(this T obj, bool ignoreInterfaceTypeFields = false, List<Tuple<Type, string>> ignoreTypeList = null)
{
return Serialize<T>(obj, ignoreInterfaceTypeFields, ignoreTypeList);
}
This Serialize method can be called without params:
sClient = client.Serialize();
or manually excluding unwanted fields:
var ignoreTypeList = new List<Tuple<Type, string>>
{
new Tuple<Type, string>(client.GetType(), "Password"), // unwanted field (directly declared in "Client" class)
new Tuple<Type, string>(typeof(System.ComponentModel.Component), "Site") // unwanted field (declared in "System.ComponentModel.Component" ancestor class of "Client" class)
};
sClient = client.Serialize(false, ignoreTypeList);
or excluding unwanted fields AND interface type fields:
var ignoreTypeList = new List<Tuple<Type, string>>
{
new Tuple<Type, string>(client.GetType(), "Password") // unwanted field (directly declared in "Client" class)
};
sClient = client.Serialize(true, ignoreTypeList);
NOTE: with framework 4.7.2 or later (or using System.ValueTuple nuget) the syntax of Tuples can be made more readable:
public static string Serialize<T>(T obj, bool ignoreInterfaceTypeFields = false, List<(Type type, string member)> ignoreTypeList = null)
and:
var ignoreTypeList = new List<(Type, string)>
{
new (client.GetType(), "Password"),
new (typeof(System.ComponentModel.Component), "Site")
};