Let's start with the following code (Please note the commented-out block):
public sealed class AnotherTest
{
public sealed class MyBagContainer<T>
{
[XmlArray("Bag", Namespace = "myNs"),
XmlArrayItem("li", Namespace = "myNs2")]
public List<T> Items { get; set; } = new List<T> { };
}
public sealed class MyListableObject1
{
[XmlElement(Namespace = "myNs3")]
public int SomeInt { get; set; }
}
public sealed class MyListableObject2
{
[XmlElement(Namespace = "myNs3")]
public bool SomeBool { get; set; }
}
public sealed class SomeObject
{
public SomeObject()
{
Xmlns.Add("myNs", "http://example.com/ns");
Xmlns.Add("myNs2", "http://example.com/ns2");
Xmlns.Add("myNs3", "http://example.com/ns3");
}
[XmlElement(Namespace = "myNs2")]
public MyBagContainer<MyListableObject1> MyBag1 { get; set; }
= new MyBagContainer<MyListableObject1>
{
Items =
{
{ new MyListableObject1 { SomeInt = 42 } },
{ new MyListableObject1 { SomeInt = 43 } }
}
};
[XmlElement(Namespace = "myNs2")]
public MyBagContainer<MyListableObject1> MyBag2 { get; set; }
= new MyBagContainer<MyListableObject1>
{
Items =
{
{ new MyListableObject1 { SomeInt = 44 } },
{ new MyListableObject1 { SomeInt = 45 } }
}
};
/*
[XmlElement(Namespace = "myNs2")]
public MyBagContainer<MyListableObject2> MyBag3 { get; set; }
= new MyBagContainer<MyListableObject2>
{
Items =
{
{ new MyListableObject2 { SomeBool = true } },
{ new MyListableObject2 { SomeBool = false } }
}
};
*/
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces Xmlns { get; set; }
= new XmlSerializerNamespaces();
}
public void Run()
{
var obj = new SomeObject();
using var ms = new MemoryStream();
using var w = XmlWriter.Create(ms, new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true
});
new XmlSerializer(obj.GetType())
.Serialize(w, obj, obj.Xmlns);
var s = System.Text.Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine(s);
}
}
When you run this, it works great. Creates everything exactly how it should be:
<SomeObject
xmlns:myNs="http://example.com/ns"
xmlns:myNs2="http://example.com/ns2"
xmlns:myNs3="http://example.com/ns3">
<MyBag1 xmlns="myNs2">
<Bag xmlns="myNs">
<li xmlns="myNs2">
<SomeInt xmlns="myNs3">42</SomeInt>
</li>
<li xmlns="myNs2">
<SomeInt xmlns="myNs3">43</SomeInt>
</li>
</Bag>
</MyBag1>
<MyBag2 xmlns="myNs2">
<Bag xmlns="myNs">
<li xmlns="myNs2">
<SomeInt xmlns="myNs3">44</SomeInt>
</li>
<li xmlns="myNs2">
<SomeInt xmlns="myNs3">45</SomeInt>
</li>
</Bag>
</MyBag2>
</SomeObject>
Now, uncomment the block of code and run it again. You'll get this error:
System.PlatformNotSupportedException: 'Compiling JScript/CSharp scripts is not supported'
With this stack trace:
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace, String location)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
at AnotherTest.Run() in AnotherTest.cs:line 92
Obviously, there are no scripts anywhere in this code.
I am assuming that's some generic error for "You put me in a pickle here, I may be able to serialize this, but how would I deserialize it?"
Is there any way to get XML serialization to work with generics? Or would I have to build the document manually (i.e. not using classes to define structure, but rather add items to an XmlDocument manually.)
The above structure has to stay as-is. I am working with a spec.
CodePudding user response:
Indeed, this error seems to be produced in several situations where the XmlSerializer encounters some limitations, ambiguities or inconsistencies.
Here, it seems to be a restriction of the XmlSerializer on .NET6 (on .NET Framework, your code works without problems). Without generics and with different XmlArray declarations ("Bag1" and "Bag2") below it works:
public sealed class MyBagContainer1
{
[XmlArray("Bag1", Namespace = "myNs"),
XmlArrayItem("li", Namespace = "myNs2")]
public List<MyListableObject1> Items { get; set; } = new List<MyListableObject1> { };
}
public sealed class MyBagContainer2
{
[XmlArray("Bag2", Namespace = "myNs"),
XmlArrayItem("li", Namespace = "myNs2")]
public List<MyListableObject2> Items { get; set; } = new List<MyListableObject2> { };
}
Both with the same name "Bag" produces the same error.