Произошла ошибка при отображении типа - проблема с сериализацией XML - PullRequest
6 голосов
/ 10 декабря 2010

У меня есть объект Dictionary, который необходимо записать в файл XML.Словарь содержит строковый тип в качестве ключа и пользовательский класс Object (производный от System.Windows.Forms.Control) в качестве значения.

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();
    }
}

Класс CommonControl выглядит следующим образом

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; }
    //}
}
}

Класс CommonControl является производным от класса Controls.

Я хочу записать вышеупомянутый словарь в файл XML.

[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();
    }

}

, для этого я использую ControlSerializerclass

И при его вызове таким образом

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

Проблема в том, что я получаю исключение, говорящее "Произошла ошибка, отражающая тип 'SharpFormEditorDemo.ControlSerializer'."

Но я получаю тип, используя оператор typeof.Озадачен, почему это происходит.Извините, если я слишком длинный, но хотел бы дать полную картину.

Спасибо

Ответы [ 4 ]

13 голосов
/ 10 декабря 2010

Универсальные словари не могут быть XmlSerialized. Полученная ошибка вызвана публичным свойством DicCtrl.

  • Используйте атрибут [XmlIgnore], чтобы пропустить это свойство при сериализации (что, вероятно, не то, что вам нужно).
  • Измените тип свойства на тип, который можно сериализовать, например, List<T>
  • Найти или реализовать сериализуемый словарь
  • Или реализовать IXmlSerializable

Кстати, атрибут [Serializable] необходим только для двоичной сериализации. Вам не нужно это для сериализации Xml.

10 голосов
/ 10 декабря 2010

Ребята .. С небольшой помощью в Интернете я нашел решение ..

Мне пришлось добавить еще один класс

[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

}

Затем использовал объект SerializableDictionary вместо обычного словаря.Также в моем классе CommonControls мне пришлось реализовать «IXmlSerializable» с помощью следующих методов.

 #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

Теперь все работает нормально.Спасибо всем.!!!

2 голосов
/ 10 декабря 2010

Я думаю, вы обнаружите, что Dictionary нельзя сериализовать с XmlSerializer

1 голос
/ 24 января 2013

Я использовал DataContractSerializer из System.Runtime.Serialization.dll.Сериализовал / десериализовал мой класс с двумя свойствами словаря без вопросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...