我有一個簡單的.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:類型「Test.Detail」和「Test.Xml.Detail」都使用命名空間''中的XML類型名稱'Detail'。使用XML屬性爲類型指定唯一的XML名稱和/或名稱空間。
我試圖標誌着派生Xml.Detail
類作爲一個匿名XML類型,但隨後的例外規定:
出現InvalidOperationException:不能包含匿名類型「Test.Xml.Detail」。
我已經閱讀了很多類似的問題,但還沒有遇到任何解決這個問題的東西。
在下面的代碼中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;
}
}
}
}
注意周圍試圖冠名的其他方式,命名派生類爲'DerivedDetail'並移除'XmlType'屬性,仍然導致了類似'XSI:在序列化元素 – Toby