- Xml ファイルを読み込むときは、基底クラスを指定する
- Xml ファイルを読み込んだ後は、拡張クラスとして扱いたい
こんな場面が多々あります。そんなときに使える方法です。
XMLファイルの読み書きに、XmlSerializer を使用します。クラスオブジェクトをXMLファイルに相互変換するイメージで使うことができます。
XMLファイルと対応するクラス
今回は、以下の構成を例にします。基底クラスとしてUserXmlクラス、拡張クラスとしてAdministratorXml、EditorXml クラスを使用します。
基底クラス
基底クラスであるUserクラスのコードです。
重要なことは、基底クラスの属性( Attribute ) にXmlInclude を設定することです。パラメータに拡張クラスの型を指定します。対応させたいすべての拡張クラスを設定します。
using System.Xml.Serialization;
namespace XmlProject
{
/// <summary>
/// ユーザーXml
/// </summary>
[XmlInclude(typeof(AdministratorXml))]
[XmlInclude(typeof(EditorXml))]
public abstract class UserXml
{
}
}
今回はUserXmlを抽象クラスとしました。抽象クラスでなくても、これから説明する方法で読み書き可能です。
拡張クラス
AdministratorXml、EditorXml クラスは、UserXmlを継承したクラスです。
AdministratorXml のコード
namespace XmlProject
{
/// <summary>
/// 管理者Xml
/// </summary>
public class AdministratorXml : UserXml
{
/// <summary>ID</summary>
public string? id;
/// <summary>パスワード</summary>
public string pass;
/// <summary>年齢</summary>
public int age;
/// <summary>年齢表示判定</summary>
public bool isViewAge;
/// <summary>役職</summary>
public string position;
public AdministratorXml()
{
id = null;
pass = "abc";
age = 30;
isViewAge = false;
position = "未設定";
}
}
}
EditorXml のコード
namespace XmlProject
{
/// <summary>
/// 編集者Xml
/// </summary>
public class EditorXml : UserXml
{
/// <summary>ID</summary>
public string? id;
/// <summary>パスワード</summary>
public string pass;
/// <summary>画像編集許可判定</summary>
public bool isEnabledEditPicture;
public EditorXml() {
id = null;
pass = "abc";
isEnabledEditPicture = false;
}
}
}
XMLファイルに書き込み
AdministratorXml クラスをUserクラスとして書き込みます。このようにXMLファイルを書くことで、読み込み時は、Userクラスとして読み込むことができます。
XMLファイル保存クラス
XmlSerializerを使用した、Xml保存クラス であるXmlSaver は↓のようになります。
XmlSaver のコード
using System.Text;
using System.Xml.Serialization;
namespace XmlProject
{
/// <summary>
/// Xmlセーバー
/// </summary>
public class XmlSaver
{
/// <summary>
/// XMLファイルに保存する
/// </summary>
/// <typeparam name="T">型</typeparam>
/// <param name="xml">Xmlとして保存するクラス</param>
/// <param name="filePath">保存するファイルパス</param>
public static void Save<T>(T xml, string filePath)
{
//XmlSerializerオブジェクトを作成
XmlSerializer serializer = new XmlSerializer(typeof(T));
//書き込むファイルを開く(UTF-8 BOM無し)
using (StreamWriter sw = new StreamWriter(filePath, false, new UTF8Encoding(false)))
{
//シリアル化し、XMLファイルに保存する
serializer.Serialize(sw, xml);
}
}
}
}
Xml 保存実行
XmlSaverを使用して、AdministratorXmlをUserXmlとして保存します。XmlSaverで保存する型をUserXmlとします。
using XmlProject;
string filePath = Environment.CurrentDirectory + "/AdministratorXml.xml";
AdministratorXml administratorXml = new AdministratorXml();
administratorXml.id = "abc";
administratorXml.pass = "abc";
administratorXml.age = 78;
administratorXml.isViewAge = true;
XmlSaver.Save<UserXml>(administratorXml, filePath);
実行した結果、UserXmlとして保存されました。
- 2行目のタグの名前がUserXmlとなっています。
- 5行目にxsi;type = “AdministratorXml” が属性があります。型がAdministratorXmlであることを表します。
XMLファイルの読み込み
先ほど保存したものをUserXml クラスの型( 基底クラスの型 )を指定して読み込みます。読み込んだものはAdministratorXml クラスの型( 拡張クラスの型 ) として扱うことができます。
XMLファイル読み込みクラス
XmlSerializerを使用してXMLファイルを読み込むXmlLoader クラスは↓のようになります。
XmlLoaderのコード
using System.Text;
using System.Xml.Serialization;
namespace XmlProject
{
/// <summary>
/// Xmlローダー
/// </summary>
internal class XmlLoader
{
// XMLファイルをロードする
public static T Load<T>(string path)
{
//XmlSerializerオブジェクトを作成
XmlSerializer serializer = new XmlSerializer(typeof(T));
//読み込むファイルを開く
using (StreamReader sr = new StreamReader(path, new UTF8Encoding(false)))
{
//XMLファイルから読み込み、逆シリアル化する
T t = (T?)serializer.Deserialize(sr) ?? throw new Exception();
return t;
}
}
}
}
Xml読み込み実行
XmlLoader を使用して、先ほど保存したXMLファイルを読み込みます。XmlLoaderで、UserXmlクラス( 基底クラス )の型を指定します。
コードは、UserXmlで読み込んだ後、UserXmlクラスの拡張クラスの型を出力しています。
using XmlProject;
Type[] userTypeTable = new Type[]
{
typeof(AdministratorXml),
typeof(EditorXml)
};
string filePath = Environment.CurrentDirectory + "/AdministratorXml.xml";
UserXml userXml = XmlLoader.Load<UserXml>(filePath);
foreach (Type t in userTypeTable)
{
if (t == userXml.GetType())
{
Console.Write("UserXml Type = " + t.Name);
}
}
このコードを実行した結果、型の名前がAdministratorXmlと出力されました。AdministratorXmlとして扱うことができます。
読み込んだUserXmlクラスのオブジェクトは、AdministratorXmlクラスに型変換することで、AdministratorXmlクラスのオブジェクトとして扱うことができます。
まとめ
C# Xml において、拡張クラスをXmlSerializerで読み書きというテーマで書きました。
コメント