XML シリアル化のオーバーライド
XmlSerializer を使用すると、一連の同じクラスを使用して、複数の XML ストリームを生成できます。このような処理が必要になるのは、2 つの異なる XML Web サービスが、細部が少し異なるだけでほぼ同じ基本情報を要求するような場合です。たとえば、書籍の注文を処理する 2 つの XML Web サービスがあり、その両方の処理で国際標準図書番号 (ISBN: International Standard Book Number) が必要だとします。1 つのサービスはタグ <ISBN> を使用し、2 番目のサービスはタグ <BookID> を使用します。ISBN
という名前のフィールドを含む Book
という名前のクラスを作成します。Book
クラスのインスタンスをシリアル化すると、既定では、メンバ名 (ISBN) がタグの要素名として使用されます。最初の XML Web サービスの場合は、この既定の動作で問題ありません。しかし、この XML ストリームを 2 番目の XML Web サービスに送信するには、タグの要素名が BookID
となるようにシリアル化をオーバーライドする必要があります。
代替要素名を持つ XML ストリームを作成するには
- XmlElementAttribute クラスのインスタンスを作成します。
- XmlElementAttribute の ElementName を "BookID" に設定します。
- XmlAttributes クラスのインスタンスを作成します。
- XmlElementAttribute オブジェクトを、XmlAttributes の XmlElements プロパティを通じてアクセスされるコレクションに追加します。
- XmlAttributeOverrides クラスのインスタンスを作成します。
- XmlAttributes をこの XmlAttributeOverrides に追加し、オーバーライドする対象のオブジェクトの型とオーバーライドされるメンバの名前を渡します。
- XmlAttributeOverrides を使用して、XmlSerializer クラスのインスタンスを作成します。
Book
クラスのインスタンスを作成し、それをシリアル化または逆シリアル化します。
このシリアル化処理の例を次に示します。
Public Class SerializeOverride()
' Creates an XmlElementAttribute with the alternate name.
Dim myElementAttribute As XmlElementAttribute = _
New XmlElementAttribute()
myElementAttribute.ElementName = "BookID"
Dim myAttributes As XmlAttributes = New XmlAttributes()
myAttributes.XmlElements.Add(myElementAttribute)
Dim myOverrides As XmlAttributeOverrides = New XmlAttributeOverrides()
myOverrides.Add(typeof(Book), "ISBN", myAttributes)
Dim mySerializer As XmlSerializer = _
New XmlSerializer(GetType(Book), myOverrides)
Dim b As Book = New Book()
b.ISBN = "123456789"
' Creates a StreamWriter to write the XML stream to.
Dim writer As StreamWriter = New StreamWriter("Book.xml")
mySerializer.Serialize(writer, b);
End Class
[C#]
public class SerializeOverride()
{
// Creates an XmlElementAttribute with the alternate name.
XmlElementAttribute myElementAttribute = new XmlElementAttribute();
myElementAttribute.ElementName = "BookID";
XmlAttributes myAttributes = new XmlAttributes();
myAttributes.XmlElements.Add(myElementAttribute);
XmlAttributeOverrides myOverrides = new XmlAttributeOverrides();
myOverrides.Add(typeof(Book), "ISBN", myAttributes);
XmlSerializer mySerializer =
new XmlSerializer(typeof(Book), myOverrides)
Book b = new Book();
b.ISBN = "123456789"
// Creates a StreamWriter to write the XML stream to.
StreamWriter writer = new StreamWriter("Book.xml");
mySerializer.Serialize(writer, b);
}
XML ストリームは、次のようになります。
<Book>
<BookID>123456789</BookID>
</Book>
クラスのオーバーライド
既存のクラスからクラスを派生させ、XmlSerializer に対してそれらのクラスをシリアル化するように指示する方法でも、代替 XML ストリームを作成できます。たとえば、上の Book
クラスを例に考えてみた場合、このクラスからクラスを派生させ、より多くのプロパティを持つ ExpandedBook
クラスを作成できます。ただし、作成した派生型をリアル化または逆シリアル化するときに受け入れるように XmlSerializer に対して指示する必要があります。このような処理を行うには、XmlElementAttribute を作成し、その Type プロパティを該当する派生クラス型に設定します。その XmlElementAttribute を XmlAttributes に追加します。次に、オーバーライドされる型、および派生クラスを受け入れるメンバの名前を指定して、XmlAttributes を XmlAttributeOverrides に追加します。この例を次に示します。
Public Class Orders
public Books() As Book
End Class
Public Class Book
public ISBN As String
End Class
Public Class ExpandedBook
Inherits Book
public NewEdition As Boolean
End Class
Public Class Run
Shared Sub Main()
Dim t As Run = New Run()
t.SerializeObject("Book.xml")
t.DeserializeObject("Book.xml")
End Sub
Public Sub SerializeObject(filename As String)
' Each overridden field, property, or type requires
' an XmlAttributes.
Dim attrs As XmlAttributes = New XmlAttributes()
' Creates an XmlElementAttribute to override the
' field that returns Book objects. The overridden field
' returns Expanded objects instead.
Dim attr As XmlElementAttribute = _
New XmlElementAttribute()
attr.ElementName = "NewBook"
attr.Type = GetType(ExpandedBook)
' Adds the element to the collection of elements.
attrs.XmlElements.Add(attr)
' Creates the XmlAttributeOverrides.
Dim attrOverrides As XmlAttributeOverrides = _
New XmlAttributeOverrides()
' Adds the type of the class that contains the overridden
' member, and the XmlAttributes to override it with, to the
' XmlAttributeOverrides.
attrOverrides.Add(GetType(Orders), "Books", attrs)
' Creates the XmlSerializer using the XmlAttributeOverrides.
Dim s As XmlSerializer = _
New XmlSerializer(GetType(Orders), attrOverrides)
' Writing the file requires a TextWriter.
Dim writer As TextWriter = New StreamWriter(filename)
' Creates the object that will be serialized.
Dim myOrders As Orders = New Orders()
' Creates an object of the derived type.
Dim b As ExpandedBook = New ExpandedBook()
b.ISBN= "123456789"
b.NewEdition = True
myOrders.Books = New ExpandedBook(){b}
' Serializes the object.
s.Serialize(writer,myOrders)
writer.Close()
End Sub
Public Sub DeserializeObject(filename As String)
Dim attrOverrides As XmlAttributeOverrides = _
New XmlAttributeOverrides()
Dim attrs As XmlAttributes = New XmlAttributes()
' Creates an XmlElementAttribute to override the
' field that returns Book objects. The overridden field
' returns Expanded objects instead.
Dim attr As XmlElementAttribute = _
New XmlElementAttribute()
attr.ElementName = "NewBook"
attr.Type = GetType(ExpandedBook)
' Adds the XmlElementAttribute to the collection of objects.
attrs.XmlElements.Add(attr)
attrOverrides.Add(GetType(Orders), "Books", attrs)
' Creates the XmlSerializer using the XmlAttributeOverrides.
Dim s As XmlSerializer = _
New XmlSerializer(GetType(Orders), attrOverrides)
Dim fs As FileStream = New FileStream(filename, FileMode.Open)
Dim myOrders As Orders = CType( s.Deserialize(fs), Orders)
Console.WriteLine("ExpandedBook:")
' The difference between deserializing the overridden
' XML document and serializing it is this: To read the derived
' object values, you must declare an object of the derived type
' and cast the returned object to it.
Dim expanded As ExpandedBook
Dim b As Book
for each b in myOrders.Books
expanded = CType(b, ExpandedBook)
Console.WriteLine(expanded.ISBN)
Console.WriteLine(expanded.NewEdition)
Next
End Sub
End Class
[C#]
public class Orders
{
public Book[] Books;
}
public class Book
{
public string ISBN;
}
public class ExpandedBook:Book
{
public bool NewEdition;
}
public class Run
{
public void SerializeObject(string filename)
{
// Each overridden field, property, or type requires
// an XmlAttributes.
XmlAttributes attrs = new XmlAttributes();
// Creates an XmlElementAttribute to override the
// field that returns Book objects. The overridden field
// returns Expanded objects instead.
XmlElementAttribute attr = new XmlElementAttribute();
attr.ElementName = "NewBook";
attr.Type = typeof(ExpandedBook);
// Adds the element to the collection of elements.
attrs.XmlElements.Add(attr);
// Creates the XmlAttributeOverrides.
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
// Adds the type of the class that contains the overridden
// member, and the XmlAttributes to override it with, to the
// XmlAttributeOverrides.
attrOverrides.Add(typeof(Orders), "Books", attrs);
// Creates the XmlSerializer using the XmlAttributeOverrides.
XmlSerializer s =
new XmlSerializer(typeof(Orders), attrOverrides);
// Writing the file requires a TextWriter.
TextWriter writer = new StreamWriter(filename);
// Creates the object that will be serialized.
Orders myOrders = new Orders();
// Creates an object of the derived type.
ExpandedBook b = new ExpandedBook();
b.ISBN= "123456789";
b.NewEdition = true;
myOrders.Books = new ExpandedBook[]{b};
// Serializes the object.
s.Serialize(writer,myOrders);
writer.Close();
}
public void DeserializeObject(string filename)
{
XmlAttributeOverrides attrOverrides =
new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes();
// Creates an XmlElementAttribute to override the
// field that returns Book objects. The overridden field
// returns Expanded objects instead.
XmlElementAttribute attr = new XmlElementAttribute();
attr.ElementName = "NewBook";
attr.Type = typeof(ExpandedBook);
// Adds the XmlElementAttribute to the collection of objects.
attrs.XmlElements.Add(attr);
attrOverrides.Add(typeof(Orders), "Books", attrs);
// Creates the XmlSerializer using the XmlAttributeOverrides.
XmlSerializer s =
new XmlSerializer(typeof(Orders), attrOverrides);
FileStream fs = new FileStream(filename, FileMode.Open);
Orders myOrders = (Orders) s.Deserialize(fs);
Console.WriteLine("ExpandedBook:");
// The difference between deserializing the overridden
// XML document and serializing it is this: To read the derived
// object values, you must declare an object of the derived type
// and cast the returned object to it.
ExpandedBook expanded;
foreach(Book b in myOrders.Books)
{
expanded = (ExpandedBook)b;
Console.WriteLine(
expanded.ISBN + "\n" +
expanded.NewEdition);
}
}
}
参照
XML シリアル化および SOAP シリアル化 | XmlSerializer | XmlElementAttributeXmlAttributes | XmlAttributeOverrides