2010-12-10 23 views
6

我有一个需要写入XML文件的Dictionary对象。 该字典包含字符串类型作为键和自定义类的对象(从System.Windows.Forms.Control派生)作为值。反映类型错误 - XML序列化问题

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是从控制类导出。

我想要做的是将上述字典写入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(); 
    } 

} 

为我使用的ControlSerializer类

而且在调用它像这样

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

的问题是,我得到一个异常说 “时出错反映类型“SharpFormEditorDemo.ControlSerializer”。“

但我得到了使用typeof运算符的类型。为什么会发生这种情况呢?对不起,如果我太长,但想给全面的照片。

感谢

+0

在异常上发布更多详情。也适用于任何InnerExceptions。 – decyclone 2010-12-10 09:51:04

+1

嗨Decyclone ... thnx提示帮助内部异常消息是这样的。是否因为我使用的字典对象不可序列化?无法序列化System.Collections.Generic.Dictionary'2 [[System.String,mscorlib,版本= 2.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089],SharpFormEditorDemo.CommonControl,SharpFormEditorDemo类型的成员SharpFormEditorDemo.ControlSerializer.DicCtrl = 1.0.3996.27187,Culture = neutral,PublicKeyToken = null]],因为它实现了IDictionary。 – JCTLK 2010-12-10 09:55:16

回答

10

家伙..随着网络上一点点的帮助,我找到了解决办法..

我不得不添加另一个类

[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

我想你会发现,Dictionary不能XmlSerializer

+1

是的,我不得不使用实现IXMlSerializable接口的自定义字典类。 – JCTLK 2010-12-14 07:15:23

13

通用词典不能XmlSerialized序列化。您收到的错误是由公共财产DicCtrl造成的。

  • 使用[XmlIgnore]属性序列化时跳过这个属性(这可能不是你想要的)。
  • 将属性的类型更改为可序列化的类型,例如List<T>
  • 查找或实现序列化的词典
  • 或实施IXmlSerializable

BTW只需要二进制序列化的[Serializable]属性。你不需要它来进行Xml序列化。

+1

感谢彼得......不幸的是,我不能使用这个[XMLIgnore],因为我想序列化它。无论如何,正如你所说,我将不得不实施一个可串行化的字典。 – JCTLK 2010-12-10 09:59:40

+1

@Janith,已经有很多实现了。请务必首先谷歌:) – Ian 2010-12-10 10:04:23

+0

@Janith:我添加了实现'IXmlSerializable'作为第四个选项。另请注意,我同意@Ian创建另一个可序列化字典似乎不是最好的解决方案 – 2010-12-10 10:08:52

1

我从System.Runtime.Serialization.dll使用DataContractSerializer。使用两个Dictionary属性对我的类进行序列化/反序列化,没有任何问题。