-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Creating an XmlSerializer object for class Container in the following example fails with
System.PlatformNotSupportedException: 'Compiling JScript/CSharp scripts is not supported'
on .NET Core.
namespace A
{
[System.Xml.Serialization.XmlType("TypeA")]
public class Test
{
public string Name { get; set; }
}
}
namespace B
{
[System.Xml.Serialization.XmlType("TypeB")]
public class Test
{
public string Name { get; set; }
}
}
public class Container
{
[System.Xml.Serialization.XmlElementAttribute("A")]
public A.Test[] A { get; set; }
[System.Xml.Serialization.XmlElementAttribute("B")]
public B.Test[] B { get; set; }
}The exception is thrown here:
runtime/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs
Lines 81 to 84 in 503d560
| if (fallbackToCSharpAssemblyGeneration) | |
| { | |
| throw new PlatformNotSupportedException(SR.CompilingScriptsNotSupported); | |
| } |
The real cause manifests itself here:
runtime/src/libraries/System.Private.Xml/src/System/Xml/Serialization/CodeGenerator.cs
Lines 261 to 269 in 503d560
| internal LocalBuilder DeclareOrGetLocal(Type type, string name) | |
| { | |
| LocalBuilder? local; | |
| if (!_currentScope!.TryGetValue(name, out local)) | |
| local = DeclareLocal(type, name); | |
| else | |
| Debug.Assert(local.LocalType == type); | |
| return local; | |
| } |
This assert fails because XmlSerializationWriterILGen creates keys for local variables only based on the name of their type and without accounting for namespaces. In the example, it creates a key named aArrayOfTest for a local variable of type A.Test[]. It creates the same key (aArrayOfTest) for a variable of type B.Test[] and finds the local variable which has the same key but is of type A.Test[].
runtime/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriterILGen.cs
Line 1413 in 503d560
| string aName = "a" + arrayTypeDesc.Name; |
This issue only occurs for arrays (or other collections) because for non-array properties no local variables get generated.
The issue surfaces only on .NET Core because on .NET Framework the serializer falls back to creating an assembly from source using CodeDom (fallbackToCSharpAssemblyGeneration above). In the generated code, separate C# scope blocks are used for each property so that the local variable name a can be reused.
I can provide a PR to fix this.