将CultureInfo对象序列化为另一个类的属性

时间:2012-10-01 22:58:43

标签: c# c#-4.0 serialization cultureinfo

因此,根据CultureInfo类规范,它是[Serializable]。但是,当我有另一个[Serializable]类(比如ClassA)具有对CultureInfo实例的引用时,我尝试使用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);
    }
}

3 个答案:

答案 0 :(得分:5)

你认为类被标记为Serializable是正确的,但在C#中有一个奇怪的地方,Seralizable并不意味着它可以序列化为所有形式。 Serializable属性仅指示可以对对象执行序列化,但不能指示可以进行哪种类型的序列化。这表示该类可以进行序列化,而不是可以执行任何序列化。 Xml序列化还有一个限制,即对象上必须有默认构造函数,请参阅MSDN documentation on XML serialization。如果您注意到序列化的文档一般没有规定此限制(Serialization Documentation)。

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

答案 1 :(得分:0)

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

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

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

ClassA内。另请参阅this article

答案 2 :(得分:0)

我建议你在序列化“UsedCulture”时尝试用字符串类型参数替换“CultureInfo”。然后在你的主代码中将其更改为“CultureInfo”类型。这是一个技巧,因为有人提到“CultureInfo无法序列化” 希望这可以帮助。 Kourosh

相关问题