Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

There was an error reflecting type - XML Serialization issue

I have a Dictionary object which needs to be written into an XML file. The dictionary contains String type as Key and a custom class's Object (Deriving from System.Windows.Forms.Control ) as Value.

namespace SharpFormEditorDemo
{
    [Serializable]
    public static class common
    {

    public static Dictionary<String,CommonControl > dicControls = new Dictionary<string, CommonControl>();

    public static Object objSelected = new Object();
    public static int ctrlId = 0;

    //The serialization and Deserialization methods.
    public static void Serialize(XmlTextWriter xmlTextWriter,Dictionary<String,CommonControl> dic)
    {
        xmlTextWriter.WriteStartDocument();
        ControlSerializer file = new ControlSerializer(dic);
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(ControlSerializer));
        xmlSerializer.Serialize(xmlTextWriter, file);

        xmlTextWriter.WriteEndDocument();
    }
}

The class CommonControl is like this

namespace SharpFormEditorDemo
{

public class CommonControl : System.Windows.Forms.Control 
{

    //private List<String> controls;
    private String sql;
    private int minVal; //Minimum value for a field
    private int maxVal; //Maximum value for a field
    private string displayValue; //Display Value        
    private string keyValue; //Key Value
    private string clickEvent; //Click event
    private string selectedIndexChangeEvent; //Combo box event.
    private string validateEvent; //Validated event.



    public string SelectedIndexChangeEvent
    {
        get { return selectedIndexChangeEvent; }
        set { selectedIndexChangeEvent = value; }
    }

    public string ClickEvent
    {
        get { return clickEvent; }
        set { clickEvent = value; }
    }

    public string ValidateEvent
    {
        get { return validateEvent; }
        set { validateEvent = value; }
    }

    public string KeyValue
    {
        get { return keyValue; }
        set { keyValue = value; }
    }

    public string DisplayValue
    {
        get { return displayValue; }
        set { displayValue = value; }
    }

    public int MinVal
    {
        get { return minVal; }
        set { minVal = value; }
    }       

    public int MaxVal
    {
        get { return maxVal; }
        set { maxVal = value; }
    }     

    public String Sql
    {
        get { return sql; }
        set { sql = value; }
    }

    //public List<String> Controls
    //{
    //    get { return controls; }
    //    set { controls = value; }
    //}
}
}

The class CommonControl is a deriving from Controls class.

What I want to do is to write the Above said dictionary to an XML file.

[Serializable]
public class ControlSerializer : ISerializable
{
    public ControlSerializer()
    {
    }


    private Dictionary<String, CommonControl> dicCtrl;

    public Dictionary<String, CommonControl> DicCtrl
    {
        get { return dicCtrl; }
        set { dicCtrl = value; }
    }


    public ControlSerializer(Dictionary<String, CommonControl> dic)
    {           
        this.DicCtrl = dic;
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        throw new NotImplementedException();
    }

}

for that I'm using the ControlSerializer class

And in calling it like this

 try
        {
            XmlTextWriter xlw = new XmlTextWriter(@"D:\Test.xml", null);
            common.Serialize(xlw, common.dicControls);
        }
        catch (Exception exShow)
        {

The problem is that I'm getting an exception saying "There was an error reflecting type 'SharpFormEditorDemo.ControlSerializer'."

But I'm getting the type using typeof operator. Baffled on why this is happening. Sorry If I'm too lengthy but wanted to give the full picture.

Thanks

like image 988
JCTLK Avatar asked Dec 10 '10 09:12

JCTLK


4 Answers

Generic dictionaries cannot be XmlSerialized. The error you get is caused by the public property DicCtrl.

  • Use the [XmlIgnore] attribute to skip this property when serializing (which is probably not what you want).
  • Change the type of the property to a type that can be serialized e.g. List<T>
  • Find or implement a serializable dictionary
  • Or implement IXmlSerializable

BTW the [Serializable] attribute is only needed for binary serialization. You do not need it for Xml serialization.

like image 111
heijp06 Avatar answered Jan 28 '23 05:01

heijp06


Guys.. With a little help on web I found a solution..

I had to add another class

[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue>: Dictionary<TKey, TValue>, IXmlSerializable
{      

    #region IXmlSerializable Members
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }


    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue)); 

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read(); 

        if (wasEmpty)
            return; 

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");
            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();
            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();
            this.Add(key, value);
            reader.ReadEndElement();
            reader.MoveToContent();
        }

        reader.ReadEndElement();
    }



    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue)); 

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");
            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();
            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }

    }

    #endregion

}

Then used the SerializableDictionary object instead of normal Dictionary. Also in my CommonControls class I had to implement "IXmlSerializable" with following methods.

 #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotImplementedException();
    }

    #endregion

Now the whole thing is working ok. Thanks Everyone. !!!

like image 43
JCTLK Avatar answered Jan 28 '23 06:01

JCTLK


I think you'll find that Dictionary cannot be serialized with XmlSerializer

like image 33
Dean Chalk Avatar answered Jan 28 '23 05:01

Dean Chalk


I used DataContractSerializer from System.Runtime.Serialization.dll. Serialized/deserialized my class with two Dictionary properties without any questions.

like image 28
s_tranquil Avatar answered Jan 28 '23 06:01

s_tranquil