【问题标题】:.NET 4.5.1 WCF Serialization exception.NET 4.5.1 WCF 序列化异常
【发布时间】:2014-02-11 17:12:18
【问题描述】:

我们的 LOB 应用程序是一个使用 CSLA 业务对象的客户端服务器应用程序,这些业务对象正在使用 NetDataContractSerializer 进行序列化。服务器端在 WCF 上运行,客户端有端点。

当客户端软件从安装了 .NET 4.5 的 Windows 7 或 Windows 8 运行时,这一切都有效。

在装有最新 .NET 4.5.1 Framework 的 Windows 8 或 Windows 8.1 上运行客户端软件时,会出现以下异常。

格式化程序在尝试反序列化 消息:尝试反序列化参数时出错 http://ws.lhotka.net/WcfDataPortal:FetchResult。内部异常 消息是“第 1 行位置 11619 中的错误。”元素 命名空间中的“m_serializationArray” 'http://schemas.microsoft.com/2003/10/Serialization/Arrays' 不是 预期的。期待元素'm_keyRehashCount'。'。请参见 InnerException 了解更多详情。

最内在的例外是

第 1 行位置 11619 出错。“元素”“m_serializationArray”来自 命名空间'http://schemas.microsoft.com/2003/10/Serialization/Arrays' 预计不会。期待元素“m_keyRehashCount”。

我在 stackoverflow 或谷歌上找不到任何关于此的信息,我在 CSLA 论坛上发布了同样的问题,也许我也应该在 Connect 上发布它。但也许我在这里很幸运?

在将 .NET Framework 更新到 4.5.1 之前,我需要一些时间来备份我的开发环境

我能想到两种可能的解决方案:

  • 将 2008 服务器升级到 .NET 4.5.1。
  • 强制客户端软件使用 .NET 4.5

是否可以强制客户端软件仅使用 .NET 4.5? 还有什么想法吗?

【问题讨论】:

  • 我来自 Microsoft .net 框架兼容性团队。您能否向我们发送一个可以重现此问题的简单项目到 microsoft.com 上的 netfx45compat 以调查此问题?
  • 我会尽我所能,但接下来的几天我有点忙
  • 在模型中使用 ConcurrentDictionary 时会发生这种情况,我将发送修改后的 csla 示例项目。

标签: wcf .net-4.5 csla


【解决方案1】:

我可以从头到尾重现这个问题。在此期间,我想提供一些事实,看看这是否对您有所帮助。

根据文档,NetDataContractSerializer 比 DataContractSerializer 更具限制性。

NetDataContractSerializer 在一个重要方面与 DataContractSerializer 不同:NetDataContractSerializer 在序列化的 XML 中包含 CLR 类型信息,而 DataContractSerializer 不包含。因此,只有当序列化和反序列化端共享相同的 CLR 类型时,才能使用 NetDataContractSerializer。

我相信 4.5.1 中的 ConcurrentDictionary 类型添加了一个名为 m_keyRehashCount 的属性或成员变量,这在 4.5 版本的 ConcurrentDictionary 中是找不到的。尝试在 4.5.1 机器上反序列化此对象时 - 序列化程序预计此缺失属性会导致此异常。

  <m_keyRehashCount>0</m_keyRehashCount>

这里有几个方法可以解决这个问题:

  1. 将您的服务器机器也升级到 4.5.1。 .net 4.5.1 是对 .net 4.5 的免费升级,它还修复了 .net 4.5 中发现的一些兼容性问题。

  2. 像这样使用 DataContractSerializer 而不是 NetDataContractSerializer 不期望在序列化和序列化时完全相同的 CLR 类型 反序列化结束。

  3. 改为使用字典 我看到这种类型的 ConcurrentDictionary 有效 很好。

【讨论】:

    【解决方案2】:

    如果您之前已经序列化了包含 ConcurrentDictionary 的对象(使用 4.5.1 之前的版本进行序列化),您可以使用以下示例在 4.5.1 中对其进行反序列化。

    此示例仅通过创建可以使用 ConcurrentDictionary 序列化 XML 反序列化的新类来帮助反序列化已序列化的 ConcurrentDictionary 对象,另请参阅其他答案。

    using System;
    using System.Collections;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Text;
    using ClassLibrary1.Model;
    
    namespace SerializaerDesrializer
    {
        [DataContract]
        public class CompositeDictionaryHolder
        {
            // Old serialized data member:
            //[DataMember]
            //private MyConcurrentDictionary<int, string> _concuurentDictionary = new MyConcurrentDictionary<int, string>();
    
            private ConcurrentDictionary<int, string> _concuurentDictionaryInternal = new ConcurrentDictionary<int, string>();
    
            [DataMember]
            private InternalArray _concuurentDictionary;
    
            public CompositeDictionaryHolder()
            {
                // Just an example:
                _concuurentDictionaryInternal.TryAdd(1, "1");
                _concuurentDictionaryInternal.TryAdd(2, "2");
                _concuurentDictionaryInternal.TryAdd(3, "3");
            }
    
    
            /// <summary>
            /// Get the data array to be serialized
            /// </summary>
            [OnSerializing]
            private void OnSerializing(StreamingContext context)
            {
                // save the data into the serialization array to be saved
                _concuurentDictionary = new InternalArray(_concuurentDictionaryInternal.ToArray());
            }
    
            /// <summary>
            /// Construct the dictionary from a previously seiralized one
            /// </summary>
            [OnDeserialized]
            private void OnDeserialized(StreamingContext context)
            {
                _concuurentDictionaryInternal = new ConcurrentDictionary<int, string>(_concuurentDictionary.m_serializationArray);
            }
        }
    
        [DataContract(
            Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
        public class InternalArray
        {
            public InternalArray()
            {
    
            }
            public InternalArray(KeyValuePair<int, string>[] serializationArray)
            {
                m_serializationArrayInternal = serializationArray;
            }
    
            [DataMember]
            public KeyValuePair<int, string>[] m_serializationArray
            {
                get { return m_serializationArrayInternal; }
                set { m_serializationArrayInternal = value; }
            }
    
            private KeyValuePair<int, string>[] m_serializationArrayInternal;
        }
    }
    

    【讨论】:

    • 感谢您的回答,如果我们遇到类似的问题,我可以随时调查。无论如何,Praburaj 已经回答了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 2010-12-17
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 2012-03-19
    相关资源
    最近更新 更多