【问题标题】:Serializing Dictionary<string, object> when dictionary was initialized with case insensitive string comparer使用不区分大小写的字符串比较器初始化字典时序列化 Dictionary<string, object>
【发布时间】:2014-07-18 22:38:19
【问题描述】:

我正在将字典序列化为 XML。当我创建一个新字典时,我使用构造函数来提供 EqualityComparer,例如不带大小写

var tabs = new Dictionary<string,Tab>(StringComparer.OrdinalIgnoreCase);

然后我序列化为 XML,当我反序列化时,有关大小写的信息会丢失 - 反序列化是使用 GenericEqualityComparer 对字典进行的,这显然是区分大小写的,因为如果它们没有正确大小写,它就找不到我的密钥。

有什么想法可以改变它吗?

一种方法是创建一个新字典并将数据从反序列化复制到新字典,但这似乎很麻烦。

更新:

反序列化一直有效,只是它将序列化的字典反序列化为不使用不区分大小写键的字典。

【问题讨论】:

  • 使用DataContract时会不会出现这个问题?
  • 是的,包含 Dictionary 类型的属性的类被标记为 DataContract,而该属性被标记为 DataMbember,如果你想知道的话
  • 是的,它是,但现在你发现它可以在 .NET 4.0 中工作,我没有什么可跟进的了。恭喜您解决了自己的问题。
  • 实际上不,序列化/反序列化一直有效,它是反序列化到不区分大小写的字典不起作用。仍然。
  • 我刚刚使用 Reflector 检查了 .NET 4.0,很明显 OnDeserialization 方法可以正确处理比较器。您是否尝试过利用SerializableAttribute

标签: c# dictionary xml-serialization .net-4.0


【解决方案1】:

我知道这个问题已经很老了,但我最近发现自己正在寻找如何做到这一点。

使用 .Net4(就像@mare 所说的那样),您可以创建一些非常好的扩展方法,让这变得轻而易举。查看https://stackoverflow.com/a/5941122/435460 以获得一个不错且简单的实现。

经过大量挖掘,这对我来说就像一个魅力。

【讨论】:

    【解决方案2】:

    编辑:

    根据 cmets,看来这种方法在 .NET 4 中可能已经过时了。

    结束编辑

    字典恰好需要一些帮助来进行序列化和反序列化。

    这是一个很好的 XML 可序列化字典示例:

    http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx

    您可以通过更改类声明并添加构造函数以及调整一行来使其不区分大小写。

    ** 编辑:更正了下面的语法错误。 /编辑**

    public class SerializableDictionary<TValue>
        : Dictionary<string, TValue>, IXmlSerializable
    {
        public SerializableDictionary()
            : base(StringComparer.InvariantCultureIgnoreCase)
        {
        }
    
        // ...
    }
    

    this.Add(key, value); 行更改为this[key] = value;

    无论如何,您可能需要调整一些细节,但这应该能让您顺利上路。

    【讨论】:

    • 使用 .NET 4 似乎通用字典是可序列化的,因为它对我有用。我不确定从 2006 年开始实施解决方案是否可取,因为新的 Dictionary 实现或 DataContractSerializer 的实现支持开箱即用的 Dictionary 序列化/反序列化。
    • @mare:嘿,这是个好消息!请考虑将标签更新为 .NET 4,我将在我的帖子上进行编辑。
    • Type parameter declaration must be an identifier not a type for string in SerializableDictionary&lt;string, TValue&gt; 后无法编译。
    • @Joe - 正确。从第一行删除string, 。无论如何,它是一个不完整的实现,已被 .NET 框架的最后几个版本所取代。我个人更喜欢接受的答案。
    • 是的,但在 3.5 中这是更好的实现 afaik。不喜欢new Dictionay&lt;&gt;(IDictionary),因为构造函数在幕后做了foreach,呸:(
    【解决方案3】:

    你只需要在构造函数中包装你的新字典:

    Dictionary<string, Tab> tabs ;
    tabs = new Dictionary<string, Tab>((Dictionary<string, Tab>)serializer.ReadObject(reader),StringComparer.OrdinalIgnoreCase);
    

    【讨论】:

      【解决方案4】:

      我意识到一个老问题,但只是通过源代码挖掘到 Dictionary 并注意到它实际上应该序列化比较器:

      info.AddValue(ComparerName, comparer, typeof(IEqualityComparer<tkey>));
      

      然后在IDeserializationCallback.OnDeserialization 的实现中检索比较器:

      comparer = (IEqualityComparer<tkey>)m_siInfo.GetValue(ComparerName, typeof(IEqualityComparer<tkey>));
      

      实现接口IDeserializationCallback 的类指定了一个方法,该方法应在实例被反序列化之后但在其返回到您的代码之前执行。

      Ref:Dictionary.csGetObjectData 和 OnDeserialization 方法

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多