XML Serialization Error - There was an error reflecting type
OK. I just encountered this. And solved it using a wrapper object.
What I did was to create a simple wrapper object for the thing I want to serialize. I my case it is a ConfigurationCollection. I serialize that and create a couple adapters to map from the serializable object to the actual object and vice versa.
using system.Xml.Serialization;
// This is an XML wrapper for FolderElement.
public class FolderAttributes
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("Volume")]
public string Volume { get; set; }
[XmlAttribute("Path")]
public string Path { get; set; }
[XmlAttribute("Selected")]
public bool Selected { get; set; }
[XmlAttribute("Active")]
public bool Active { get; set; }
/// <summary>
/// Factory Method.
/// Create new instance of FolderAttributes from FolderElment.
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public static FolderAttributes FromElement(FolderElement element)
{
return new FolderAttributes()
{
Name = element.Name,
Volume = element.VolumeLabel,
Path = element.Path,
Selected = element.Selected,
Active = element.Active
};
}
/// <summary>
/// Convert this instance to a FolderElement.
/// </summary>
/// <returns></returns>
public FolderElement ToElement()
{
return new FolderElement()
{
Name = Name,
VolumeLabel = Volume,
Path = Path,
Selected = Selected,
Active = Active
};
}
}
public class FolderElement : ConfigurationElement
{
protected const string NameKey = "name";
protected const string VolumeKey = "volume";
protected const string PathKey = "path";
protected const string selectedKey = "selected";
protected const string activeKey = "active";
[ConfigurationProperty(NameKey, DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base[NameKey]; }
set { base[NameKey] = value; }
}
[ConfigurationProperty(VolumeKey, DefaultValue = "", IsKey = false, IsRequired = false)]
public string VolumeLabel
{
get { return (string)base[VolumeKey]; }
set { base[VolumeKey] = value; }
}
[ConfigurationProperty(PathKey, DefaultValue = "", IsKey = false, IsRequired = true)]
public string Path
{
get { return (string)base[PathKey]; }
set { base[PathKey] = value; }
}
[ConfigurationProperty(selectedKey, DefaultValue = "false", IsKey = false, IsRequired = false)]
public bool Selected
{
get { return (bool)base[selectedKey]; }
set { base[selectedKey] = value; }
}
[ConfigurationProperty(activeKey, DefaultValue = "true", IsKey = false, IsRequired = false)]
public bool Active
{
get { return (bool)base[activeKey]; }
set { base[activeKey] = value; }
}
}
[ConfigurationCollection(typeof(FolderElement))]
public class FolderCollection : ConfigurationElementCollection
{
internal const string _elementName = "elements";
protected override string ElementName
{
get { return _elementName; }
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
}
protected override bool IsElementName(string elementName)
{
return elementName.Equals(_elementName, StringComparison.InvariantCultureIgnoreCase);
}
public override bool IsReadOnly()
{
return false;
}
protected override ConfigurationElement CreateNewElement()
{
return new FolderElement();
}
/// <summary>
/// Return key value for element.
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
/// <remarks></remarks>
protected override object GetElementKey(ConfigurationElement element)
{
return ((FolderElement)element).Name;
}
/// <summary>
/// Default index property.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public FolderElement this[int index]
{
get { return (FolderElement)BaseGet(index); }
}
/// <summary>
/// Returns content element by name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public FolderElement GetElementByName(string name)
{
return (FolderElement)BaseGet(name);
}
public IEnumerable<FolderElement> Elements
{
get
{
for (int index = 0; index < this.Count; index++) yield return (FolderElement)BaseGet(index);
}
}
/// <summary>
/// Add an element to the collection
/// </summary>
/// <param name="element"></param>
public void AddElement(FolderElement element)
{
BaseAdd(element);
}
}
public class FolderSection : ConfigurationSection
{
// Attribute argument must be a constant expression.
protected const string _elementsTag = "elements";
[ConfigurationProperty(_elementsTag, Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public FolderCollection Elements
{
get { return ((FolderCollection)(base[_elementsTag])); }
set { base[_elementsTag] = value; }
}
public void SaveElements(ConfigurationElementCollection elements, string path)
{
var container = new List<FolderAttributes>();
foreach (FolderElement element in elements)
{
container.Add(FolderAttributes.FromElement(element));
}
// XmlHelper.SaveXml(container, path);
SaveXml(container, path);
}
/// <summary>
/// Load elements from xml file pointed to by path.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public List<FolderElement> LoadElements(string path)
{
List<FolderElement> result = new List<FolderElement>();
var attributes = Deserialize<List<FolderAttributes>>(path);
if (attributes != null)
{
foreach (var attr in attributes)
{
var element = attr.ToElement();
result.Add(element);
}
}
return result;
}
/// <summary>
/// Save XML serialization of object to named file.
/// </summary>
/// <param name="value"></param>
/// <param name="fileName"></param>
public static void SaveXml(Object value, string fileName)
{
// First serialize the object to memory stream,
// in case of exception, the original file is not corrupted
using (MemoryStream ms = new MemoryStream())
{
var stream = new System.IO.StreamWriter(ms);
if (Serialize(value, stream))
{
// if the serialization succeeded, rewrite the file.
File.WriteAllBytes(fileName, ms.ToArray());
}
}
}
/// <summary>
/// Base-level method to serialize object to TextWriter.
/// </summary>
/// <param name="value"></param>
/// <param name="output"></param>
/// <returns></returns>
public static bool Serialize<T>(object value, TextWriter output)
{
if (value == null) throw new ArgumentNullException("Serialize(value)");
bool result = false;
Type T = value.GetType();
try
{
var xmlSerializer = new XmlSerializer(typeof(T));
using (var xmlWriter = XmlWriter.Create(output, new XmlWriterSettings { Indent = true }))
{
xmlSerializer.Serialize(xmlWriter, value);
result = true;
}
}
catch (Exception)
{
// Log.Error(ex, "WriteXml {0}", T.Name);
}
return result;
}
public static T Deserialize<T>(string fileName)
{
T result = default(T);
try
{
using (var stream = System.IO.File.OpenRead(fileName))
{
var serializer = new XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(stream);
}
}
catch (Exception)
{
// Log.Error(ex, "Deserialize<{0}> from file {1}", typeof(T).Name, fileName);
}
return result;
}
}
Saroj
Updated on June 04, 2022Comments
-
Saroj almost 2 years
I am trying to serialize few custom settings from configuration file. Below are my settings:
<FavouriteTools> <favouriteTool PluginPlaceHolder="FavoriteTool1" PlugInName="Brightness" PlugInType="2D" PlugInAssemblyName="Micro.DigiMic.Plugins.AreaBasedOnBrightness.AreaBasedOnBrightnessPlugin" GUID="0000c03a-b891-4ebd-87d7-5fbc19073a1a" /> <favouriteTool PluginPlaceHolder="FavoriteTool2" PlugInName="CircleArea" PlugInType="2D" PlugInAssemblyName="Micro.DigiMic.Plugins.CircleAreaPlugin.CircleAreaPlugin" GUID="0000c06a-b891-4ebd-87d7-5fbc19073a1a" /> <favouriteTool PluginPlaceHolder="FavoriteTool3" PlugInName="Contour Area" PlugInType="2D" PlugInAssemblyName="Micro.DigiMic.Plugins.ContourAreaPlugin.ContourAreaPlugin" GUID="0000c11a-b891-4ebd-87d7-5fbc19073a1a" />
But I get error during serializing them. Here are my classes.
//FavouriteTools - Root Node [Serializable] [XmlType("FavoriteTools")] [ConfigurationCollection(typeof(FavouriteTool), AddItemName = "favouriteTool", CollectionType = ConfigurationElementCollectionType.BasicMap)] public class FavouriteToolsCollection : ConfigurationElementCollection { //Few plublic methods here } //favouriteTool - Child node [Serializable] [XmlType("favouriteTool")] public class FavouriteTool : ConfigurationElement { /// <summary> /// Gets or sets value of Plugin PlaceHolder. /// </summary> /// <value>Text Color.</value> [ConfigurationProperty("PluginPlaceHolder", IsRequired = false)] public string PlugPlaceHolder { get { return (string)base["PluginPlaceHolder"]; } set { base["PluginPlaceHolder"] = value; } } //Few more properties like above } I am trying to serialize below class, but gets exception on below like XmlSerializer xmlinf = new XmlSerializer(data.GetType()); `data` is `ExportUser` [Serializable] public class ExportUser { public bool IsMetric { get; set; } [XmlArray("FavoriteTools")] [XmlArrayItem("favouriteTool")] public FavouriteToolsCollection FavoriteTools { get; set; } }
I get this error -
There was an error reflecting type 'ExportUser'
and in inner exception the error says -There was an error reflecting type 'FavoriteTools'
.Is there anything missing?
Update:
After seeing the inner exception, the error is
{"You must implement a default accessor on System.Configuration.ConfigurationLockCollection because it inherits from ICollection."}
There was an error reflecting type 'Zeiss.Micro.DigiMic.Application.FavouriteTool'.
But I do have a default accessor in
FavouriteToolsCollection
class:public FavouriteTool this[int index] { get { return (FavouriteTool)BaseGet(index); } set { if (this.BaseGet(index) != null) { this.BaseRemoveAt(index); } this.BaseAdd(index, value); } }
What more is missing?
-
Marc Gravell over 10 yearsWhat was the inner exception of the inner exception? (etc) - it actually gives really detailed messages if you keep drilling. Btw - did it actually say
...reflecting type 'FavoriteTools'
? because in the code: that isn't a type -
Saroj over 10 years@MarcGravell -
For non-array types, you may use the following attributes: XmlAttribute, XmlText, XmlElement, or XmlAnyElement.
- Here is the exact message with innerExceptionThere was an error reflecting type 'FavoriteTools'
-