【问题标题】:Serialization of CultureInfo object as property of another class将 CultureInfo 对象序列化为另一个类的属性
【发布时间】:2012-10-01 22:58:42
【问题描述】:

因此,根据 CultureInfo 类规范,它是 [Serializable]。但是,当我有另一个具有对 CultureInfo 实例的引用的 [Serializable] 类(例如 ClassA),并且我尝试使用 ClassA 创建一个 XmlSerializer 实例时,我得到了一个异常。有人知道解决方法吗?我会假设因为 CultureInfo 是 [Serializable],所以下面应该可以工作。

非常感谢!

-- 代码--

using System;
using System.Xml.Serialization;
using System.Globalization;

namespace CultureInfoSerializationTest
{
    class Program
    {
        static void Main(string[] args)
        {
            ClassA aClass = new ClassA();
            aClass.UsedCulture = CultureInfo.CurrentCulture;

            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ClassA));
            } catch (Exception e) { }
        }
    }

    [Serializable]
    public class ClassA
    {
        public CultureInfo UsedCulture { get; set; }
    }
}

--异常--

System.InvalidOperationException was caught
  HResult=-2146233079
  Message=There was an error reflecting type 'CultureInfoSerializationTest.ClassA'.
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
       at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
       at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
       at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
       at System.Xml.Serialization.XmlSerializer..ctor(Type type)
       at CultureInfoSerializationTest.Program.Main(String[] args) in c:\users\asbeug\documents\visual studio 2010\Projects\CultureInfoSerializationTest\CultureInfoSerializationTest\Program.cs:line 18
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=Cannot serialize member 'CultureInfoSerializationTest.ClassA.UsedCulture' of type 'System.Globalization.CultureInfo', see inner exception for more details.
       Source=System.Xml
       StackTrace:
            at System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type)
            at System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo)
            at System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo)
            at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
            at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
            at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
       InnerException: System.InvalidOperationException
            HResult=-2146233079
            Message=System.Globalization.CultureInfo cannot be serialized because it does not have a parameterless constructor.
            InnerException: 

--附加类--(来自下面的答案)

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

    public CultureInfo UsedCulture { get; set; }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (info == null)
        {
            throw new ArgumentNullException("info");
        }

            info.AddValue("Culture", UsedCulture);
    }
}

【问题讨论】:

    标签: c# c#-4.0 serialization cultureinfo


    【解决方案1】:

    您是正确的,该类被标记为可序列化,但在 C# 中有一件奇怪的事情,其中​​可序列化并不意味着它可序列化到所有形式。 Serializable 属性仅表示可以对对象执行序列化,而不表示可以进行何种类型的序列化。这表示该类有资格进行序列化,而不是可以执行任何序列化。 Xml 序列化有一个额外的限制,即对象上必须有一个默认构造函数,请参阅MSDN documentation on XML serialization。如果您注意到有关序列化的文档通常没有说明此限制 (Serialization Documentation)。

    如果您考虑一下这些不同的序列化是如何在幕后工作的,那么其原因应该很清楚。如果您正在执行二进制序列化,则不需要使用构造函数来创建对象,因为类型信息已编码在对象中。对于 Xml 序列化,您只需拥有字段,因此您所能做的就是创建一个新对象并填充它。 See this post for some discussion around this。该帖子还引用了 MSDN 关于这如何可能(使用 FormatterServices.GetUninitializedObject())的缺点。

    【讨论】:

      【解决方案2】:

      您需要通过执行public class ClassA : Iserializable 来实现接口ISerializable。此外,您必须实现方法GetObjectData。一种方法可能是添加:

      public void GetObjectData(SerializationInfo info, StreamingContext context)
          {
              if (info == null)
                  throw new ArgumentNullException("info");
      
              info.AddValue("Culture", UsedCulture);
          }
      

      ClassA 内。另请参阅this article

      【讨论】:

      【解决方案3】:

      我建议您在序列化“UsedCulture”时尝试将“CultureInfo”替换为字符串类型参数。然后在您的主代码中将其更改为“CultureInfo”类型。这是一个技巧,因为它被提到“CultureInfo 不能被序列化” 希望这可以帮助。 库罗什

      【讨论】:

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