Reputation: 647
So, according to CultureInfo class specifications, it is [Serializable]. However, when I have another [Serializable] class (say ClassA) that has a reference to a CultureInfo instance, and I try to create an XmlSerializer instance with ClassA, I get an exception. Anyone know a work around? I would assume since CultureInfo is [Serializable] the below should work.
Many thanks!
-- Code--
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; }
}
}
--Exception--
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:
--Appended class-- (from answer below)
[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);
}
}
Upvotes: 2
Views: 5825
Reputation: 21
I suggest you try to replace "CultureInfo" with a string type parameter when serializing for "UsedCulture". Then within you main code change it to "CultureInfo" type. This is a trick as it was mentioned "CultureInfo cannot be serialized" Hope this helps. Kourosh
Upvotes: 0
Reputation: 10814
You are correct that the class is marked as Serializable but there is an odd thing in C# where Seralizable doesn't mean that it is serializable to all forms. The Serializable attribute only indicates that serialization can be performed on the object but not what type of serialization is possible. This says that the class is eligable for serialization not that any serialization can be performed. Xml Serialization has an additional restriction that there must be a default constructor on the object see MSDN documentation on XML serialization. If you notice the documentation on serialization in general does not have this restriction stated (Serialization Documentation).
If you think about how these different serializations work underneath the hood the reason for this should be clear. If you are doing binary serialization the constructor does not need to be used to create the object because the type information is encoded in the object. For Xml Serialziation you just have the fields so all you can do is create a new object and populate it. See this post for some discussion around this. The post also quotes MSDN about how this is possible (the use of FormatterServices.GetUninitializedObject()) the drawbacks around this.
Upvotes: 5
Reputation: 4264
You need to implement the interface ISerializable
by doing public class ClassA : Iserializable
. Further, you have to implement the method GetObjectData
. One way might be to add:
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException("info");
info.AddValue("Culture", UsedCulture);
}
inside ClassA
. Also, see this article.
Upvotes: 0