我有一个简单的.Net框架C#控制台应用程序,它序列化一个派生类型的类,其中属性也是派生类型。
派生类的名称与基类相同,但它们位于不同的名称空间中以防止它们发生冲突。虽然XmlSerializer
使用的反射似乎并不适用于此。也许有一些方法可以纠缠我仍然可以使用漂亮名称的基类(因为它在使用时将是一个DLL接口),并且XML也使用漂亮的名称(因为它将是人类可编辑的)。 。派生类的漂亮名称不是必需的(尽管会是奖金)。
希望XML看起来像:
<?xml version="1.0" encoding="utf-8"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Details>
<Detail>
<Description>bald</Description>
</Detail>
<Detail>
<Description>red tie</Description>
</Detail>
</Details>
</Person>
但是我能得到的最接近的是<Detail>
元素
<Detail xsi:type="DerivedDetail"> ... </Detail>
必须添加此xs:type
属性不适合人工可编辑的XML。
这是通过以下C#代码实现的。如果我删除标记的XmlType
属性,那么元素应该序列化而没有xsi:type
属性,但我得到一个例外:
InvalidOperationException:Types&#39; Test.Detail&#39;和&#39; Test.Xml.Detail&#39;两者都使用来自命名空间的XML类型名称&#39; Detail&#39;&#39;。使用XML属性为类型指定唯一的XML名称和/或命名空间。
我尝试将派生的Xml.Detail
类标记为匿名XML类型,但是异常读取:
InvalidOperationException:不能包含匿名类型&#39; Test.Xml.Detail&#39;。
我已经阅读了许多类似的问题,但还没有遇到任何可以解决这个问题的问题。
在下面的代码中,Person
是一个抽象类,其属性是抽象类型Detail
的数组。这些类型分别由Xml.Person
和Xml.Detail
派生。该程序创建一个测试Xml.Person
对象并尝试序列化它:
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace Test
{
class Program
{
static void Main(string[] args)
{
// Create test details array
var TestDetails = new Xml.Detail[]
{
new Xml.Detail
{
Description = "bald"
},
new Xml.Detail
{
Description = "red tie"
}
};
// create test person object that holds details array
var TestBar = new Xml.Person()
{
Details = TestDetails
};
// serialize the person object
var s = new Xml.Serializer();
var TestOutput = s.Serialize(TestBar);
Console.WriteLine(TestOutput);
}
}
// base classes
public abstract class Person
{
public abstract Detail[] Details { get; set; }
}
public abstract class Detail
{
public abstract string Description { get; set; }
}
namespace Xml
{
// derived classes
[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(IsNullable = false)]
public class Person : Test.Person
{
[XmlArrayItem("Detail", typeof(Detail))]
[XmlArray(IsNullable = false)]
public override Test.Detail[] Details { get; set; }
}
// This attribute makes serialization work but also adds the xsi:type attribute
[XmlType("DerivedDetail")]
[Serializable]
public class Detail : Test.Detail
{
public override string Description { get; set; }
}
// class that does serializing work
public class Serializer
{
private static XmlSerializer PersonSerializer =
new XmlSerializer(typeof(Person), new Type[] { typeof(Detail) });
public string Serialize(Test.Person person)
{
string Output = null;
var Stream = new MemoryStream();
var Encoding = new UTF8Encoding(false, true);
using (var Writer = new XmlTextWriter(Stream, Encoding))
{
Writer.Formatting = Formatting.Indented;
PersonSerializer.Serialize(Writer, person);
Output = Encoding.GetString(Stream.ToArray());
}
Stream.Dispose();
return Output;
}
}
}
}
答案 0 :(得分:1)
Not sure why you're using base classes instead of interfaces when you don't have any member fields. Regardless, I assumed you wanted None
to be a concrete instantiation of abstract Col1 Col2 Col3 Col4 Col5 Col6 Col7
1 Shop1 Mon open 6am Close 4pm
2 Shop1 Tue Open 6am Close 5pm
3 shop1 Wed Open 6am Close 4pm
4 Shop2 Mon open 10am Close 3pm
5 Shop2 Tue open 11am Close 2pm
or any classes derived from abstract Col1 Col2 Col3 Col4 Col5 Col6 Col7 col8 col9 col10 Col11 Col12
1 Shop1 Mon open 6am Close 4pm Tue Open 6am Close 5pm
2 Shop2 Mon open 10am close 4pm Tue open 11am close 2pm
without decorating abstract Xml.Person
with XML attributes. I accomplished this by forcing abstract Person
to become a concrete instantiation of Person
before serializing it. Please replace Person
with Person
.
Xml.Person