Created attachment 4080 [details]
CmdLine sample to replicate the crash
Using XElement (from System.Xml.Linq) instead of XmlElement as a field/property causes an InvalidCastException when deserializing the class using the XmlSerializer:
public XElement MyAnyData; // instead of XmlElement
.The NET Framework 3.5/4.0 allows to use XElement in place of XmlElement not requiring any cast or additional code.
Mono 2.8 and 3.0.10 are crashing instead, trying to internally cast XmlElement to XElement instead.
This shows that actually the XElement is partially supported by XmlElement; but it is however failing to transfer the read XML data to an XElement instance.
Please find the attached small command-line based solution that replicates the wrong behavior in few lines. Using Xamarin Studio it is possible to run the sample and to quickly switch from .NET Framework to Mono to compare the wrong behavior with the expected one.
I've tested the application on Windows, but mono will crash on Xamarin Android too.
The usage of LINQ classes instead of System.Xml ones is offering so many advantage to justify this issue to be fixed soon.
Full exception stack:
Unhandled Exception: System.ArgumentException: Object type System.Xml.XmlElement cannot be converted to target type: System.Xml.Linq.XElement
Parameter name: val at System.Reflection.MonoField.SetValue (System.Object obj, System.Object val, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) [0x000e3] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\corlib\System.Reflection\MonoField.cs:158
at System.Reflection.FieldInfo.SetValue (System.Object obj, System.Object value) [0x00000] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\corlib\System.Reflection\FieldInfo.cs:139
at System.Xml.Serialization.XmlTypeMapMember.SetValue (System.Object ob, System.Object value) [0x00045] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlTypeMapMember.cs:103
at System.Xml.Serialization.XmlSerializationReaderInterpreter.SetMemberValue (System.Xml.Serialization.XmlTypeMapMember member, System.Object ob, System.Object value, Boolean isValueList) [0x0001a] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:583
at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadMembers (System.Xml.Serialization.ClassMap map, System.Object ob, Boolean isValueList, Boolean readBySoapOrder) [0x00903] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:478
at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadClassInstanceMembers (System.Xml.Serialization.XmlTypeMapping typeMap, System.Object ob) [0x00000] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:240
at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadClassInstance (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, BooleancheckType) [0x000df] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:230
at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadObject (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, Boolean checkType) [0x00031] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:193
at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot (System.Xml.Serialization.XmlTypeMapping rootMap) [0x00057] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:184
at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot () [0x00028] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializationReaderInterpreter.cs:87 at System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.Serialization.XmlSerializationReader reader) [0x0001c] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System.XML\System.Xml.Serialization\XmlSerializer.cs:361
Marek, could you take a look at this one?
Unfortunately this bug prevents to use PCL assemblies on a mono/Xamarin environment.
PCL subsets only allow the LINQ XElement (or even System.Object) to be used as class member, the underlying type XmlElement is pruned away in all PCL Profiles.
If we wants to use PCL for common shared assemblies no workarounds seems to be possible. Even trying to force Object as underlying type for a XmlAnyElement decorated member, the resulting type would always be an XmlElement instance, inaccessible from PCL.
A feasible fix is to allow the System.Xml.Linq assembly to inject some conversion code from XmlElement to XElement type.
Please find attached a proposed patch.
(However with this simple fix the developer should force the execution of the XElement.cctor() before being able to deserialize the sample class in the example. A valid CLR module initializers or some custom AppDomain hook should be implemented to make the sample working without any other workaround).
Fixed; mono/master 2d573ae.
This fix is in the mono-3.4.0-branch, and has been released to the Alpha channel with Mono 3.4.0 (d4511ef).
Unfortunately I need to reopen the issue.
Even if the case of single XElement is now fixed, I've just realized that the case of XElement is still not supported.
So basically, the same original project will still crash with this simple change:
public XElement MyAnyData; // instead of XmlElement
Naturally .NET supports that behavior. Mono still crashes, but XmlElement is supported.
Tested with mono 3.10.0 (Xamarin iOS).
Any news on this issue? This is so old!
I also have the same issue as stated in last comment!
Fixed in master and C9 branch