Skip to content

XmlSerializer constructor fails if type has array properties with same class name but different namespaces #46196

Closed
@mganss

Description

@mganss

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:

if (fallbackToCSharpAssemblyGeneration)
{
throw new PlatformNotSupportedException(SR.CompilingScriptsNotSupported);
}

The real cause manifests itself here:

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[].

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions