Serialization breaks in .NET 4.5
In 4.5, the implementation of XmlSerializer was replaced with one that isn't dependent on the C# compiler. While it provides better startup performance and stability, you might be running into a compatibility issue between the implementations. Can you try adding the following to your app.config file and see if that fixes the issue?
<configuration>
<system.xml.serialization>
<xmlSerializer useLegacySerializerGeneration="true"/>
</system.xml.serialization>
</configuration>
If you're concerned about having this work on 4.0, you could try detecting the version of the framework at runtime, and dynamically change the configuration if the runtime is 4.5 or higher. I wrote a blog post a while back explaining how to do that:
http://blogs.msdn.com/b/youssefm/archive/2010/01/21/how-to-change-net-configuration-files-at-runtime-including-for-wcf.aspx
.NET 4.5 MethodInfo serialization breaking change
Finally I've not been able to completely solve this issue by myself. I tried to implement ISerializable
using a custom implementation of MemberInfoSerializationHolder
to mimic the old behavior (just pasted code from 4.0 version). It works fine for new archives but it won't work with old (deployed) applications for this scenario.
I didn't find any way to solve this issue because already shipped applications won't work (unless a patch is applied but this was not viable).
I saw implementation changed little bit over in newer builds anyway issue is preset only if there is more than one method with same name (signature is then used) otherwise just the first (and only) one is picked without any extra check.
Error serializing inherited property in .NET 4.5
As Youssef answered on the related post :
In 4.5, the implementation of XmlSerializer was replaced with one that isn't dependent on the C# compiler. While it provides better startup performance and stability, you might be running into a compatibility issue between the implementations.
The configuration setting to use the legacySerializer does not work on 4.0 machines as the corresponding strongly typed Xml config section class does not contain a placeholder for this setting.
Both the issues are going to be addressed in an upcoming update. Until then you can work around the issue by setting the config switch in 4.5 on removing the switch on 4.0.
Why does XmlSerializer fail to serialize enum value in .Net Core but works fine in .NET Framework
Well, not knowing the reason why it differs like this. But i have a workaround like below :
public enum MyEnum
{
One,
}
public class ValueContainer
{
[XmlIgnore]
private object _value;
public object Value
{
get
{
return _value;
}
set
{
var type = value.GetType();
_value = type.IsEnum ? (int)value : value;
}
}
}
class Program
{
static void Main(string[] args)
{
var newSerializer = XmlSerializer.FromTypes(
new[] { typeof(ValueContainer))[0];
var instance = new ValueContainer();
instance.Value = MyEnum.One;
var memoryStream = new MemoryStream();
newSerializer.Serialize(memoryStream, instance);
var str = Encoding.Default.GetString(memoryStream.ToArray());
}
}
Output
<?xml version="1.0"?>
<ValueContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Value xsi:type="xsd:int">0</Value>
</ValueContainer>
EDIT : I fail to notice that value serialized as <Value>One</Value>
this work around is dirtier than previous but it works.
Fiddle
EDIT 2 : As @Victor Chelaru mentioned in the comments i decided to keep both workarounds but have to state that they both have the same drawback which is loosing type information on enum with serialized xml output.
[XmlType(typeName: "int",Namespace="http://www.w3.org/2001/XMLSchema")]
public enum MyEnum : int
{
[XmlEnum("0")]
One,
}
public class ValueContainer
{
public object Value;
}
public static void Main()
{
var newSerializer = XmlSerializer.FromTypes(new[]{typeof(ValueContainer), typeof(MyEnum)})[0];
var instance = new ValueContainer();
instance.Value = MyEnum.One;
var memoryStream = new MemoryStream();
newSerializer.Serialize(memoryStream, instance);
var str = Encoding.Default.GetString(memoryStream.ToArray());
str.Dump();
}
Fiddle
Edit 3: As @Simon Mourier mentioned in the comments above workaround can be achieved without modifying enum directly with usage of XmlAttributeOverrides
as below :
[XmlType(typeName: "int")]
public enum MyEnum : int
{
One,
}
public class ValueContainer
{
public object Value;
}
public static void Main()
{
var ov = new XmlAttributeOverrides();
ov.Add(typeof(MyEnum), nameof(MyEnum.One), new XmlAttributes { XmlEnum = new XmlEnumAttribute("0") });
var newSerializer = new XmlSerializer(typeof(ValueContainer), ov, new[] { typeof(MyEnum) }, null, null);
var instance = new ValueContainer();
instance.Value = MyEnum.One;
var memoryStream = new MemoryStream();
newSerializer.Serialize(memoryStream, instance);
var str = Encoding.Default.GetString(memoryStream.ToArray());
str.Dump();
}
Fiddle
Related Topics
C# Covariance on Subclass Return Types
Use "Real" Cultureinfo.Currentculture in Wpf Binding, Not Cultureinfo from Ietflanguagetag
Client Id for Property (ASP.NET MVC)
Kestrel Shutdown Function in Startup.Cs in ASP.NET Core
Is There a Quick Way to Get the Control That's Under the Mouse
How to Register Windows Forms with Simple Injector
Excluding Some Properties During Serialization Without Changing the Original Class
Broadcastblock with Guaranteed Delivery in Tpl Dataflow
Set Dllimport Attribute Dynamically
How to Read the Current Path of |Datadirectory| from Config Settings
Event Handlers Not Thread Safe
Ef4 Cause Circular Reference in Web Service
Wpf Clickonce Dpi Awareness Per-Monitor V2
String Interpolation with Variable Content in C#
Formatting a C# String with Identical Spacing in Between Values