XMLシリアル化を用いることで、オブジェクトの状態をファイルに保存できます。一方で保存すべき対象がアプリケーションに関するものならば、それはアプリケーション設定で管理します。
オブジェクトをストリームに変換し、ファイルへ書き込みます。
public class ClassName { public int publicField; // publicなフィールド private int privateField; // privateなフィールド (シリアル化の対象外) // get、setアクセサを有する publicなプロパティ public int Property { get { return privateField; } set { privateField = value; } } // getアクセサのみの publicなプロパティ (シリアル化の対象外) public int ReadOnliProperty { get { return privateField; } } // publicな既定のコンストラクタ public ClassName() { } }
TimeSpan構造体はXmlSerializerによりサポートされないため、代替手段を講じる必要があります。Program It: XmlSerializer Doesn't Serialize TimeSpan to XML Duration Type (2008/09/24)
シリアル化の対象となるクラス自身やそのメンバに属性を付加することで、出力されるXMLの書式を変更できます。
属性 | 機能 | 適用前 | 適用後 |
---|---|---|---|
XmlAttribute | メンバをXMLの属性とする |
<ClassName> <field>256</field> </ClassName> |
<ClassName field="256" /> |
XmlArray | 配列の名前を変更する |
<MemberName> <TypeName> <field>256</field> </TypeName> </MemberName> |
<OriginalName> <TypeName> <field>256</field> </TypeName> </OriginalName> |
XmlArrayItem | 配列の要素名を、型名から任意の名前に変更する |
<MemberName> <TypeName> <field>256</field> </TypeName> </MemberName> |
<MemberName> <OriginalName> <field>256</field> </TypeName> </MemberName> |
class Program { static void Main() { string fileName = "C:/sample.xml"; ClassName myClass = new ClassName(); myClass.publicField = 1; myClass.Property = 2; using( System.IO.TextWriter writer = new System.IO.StreamWriter( fileName ) ) { // シリアル化の対象となるクラスの型を指定して XmlSerializerを作成する System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer( typeof( ClassName ) ); // 指定のオブジェクトをシリアル化する serializer.Serialize( writer, myClass ); } } }
これを実行すると、次のようなXMLファイルが作成されます。
<?xml version="1.0" encoding="utf-8"?> <ClassName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <publicField>1</publicField> <Property>2</Property> </ClassName>
作成されたXMLファイルは、逆シリアル化によりオブジェクトに復元できます。
このサンプルではXmlSerializerのコンストラクタにTypeクラスを渡していますが、これ以外にも下表で示すコンストラクタがあります。
コンストラクタ | |
---|---|
XmlSerializer(Type) | |
XmlSerializer(Type, String) | |
XmlSerializer(Type, Type[]) | |
XmlSerializer(Type, XmlAttributeOverrides) | |
XmlSerializer(Type, XmlAttributeOverrides, Type[], XmlRootAttribute, String) | |
XmlSerializer(Type, XmlAttributeOverrides, Type[], XmlRootAttribute, String, String) | |
XmlSerializer(Type, XmlRootAttribute) | |
XmlSerializer(XmlTypeMapping) |
XmlSerializerのインスタンスの生成時、「ファイルまたはアセンブリ 'mscorlib.XmlSerializers, Version=x.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。」としてFileNotFoundException例外が発生することがあります。これはXmlSerializerのアセンブリが用意されていないのが原因であり、sgen.exeでこのファイルを作成することで解決できます。もしくはこのファイルは存在しなければ自動で作成されるため、この例外を無視しても問題はありません。c# - XmlSerializer giving FileNotFoundException at constructor - Stack Overflow
シリアル化の対象が配列の場合も同様に処理できます。
int[] array = new int[] { 1, 2, 3 }; XmlSerializer serializer = new XmlSerializer( typeof( int[] ) );
List<int> list = new List<int>(new int[] { 1, 2, 3 }); XmlSerializer serializer = new XmlSerializer( typeof( List<int> ) );
これらは次のように出力されます。
<?xml version="1.0" encoding="utf-8"?> <ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <int>1</int> <int>2</int> <int>3</int> </ArrayOfInt>
しかしArrayListのようにObject型を返すクラスでは型を特定できないため、「型 ProjectName.ClassName は指定されていません。スタティックに使用できない型を指定するには XmlInclude または SoapInclude 属性を使ってください。」としてInvalidOperationException例外が発生します。この場合にはXmlSerializerのコンストラクタで、Objectに含まれる可能性のある型をすべて指定するようにします。XmlSerializer コンストラクター (Type, Type[]) (System.Xml.Serialization) | MSDN
ArrayList obj = new ArrayList(new int[] { 1, 2, 3 }); XmlSerializer serializer = new XmlSerializer( typeof( ArrayList ), new Type[] { typeof(int) } );
<?xml version="1.0" encoding="utf-8"?> <ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <anyType xsi:type="xsd:int">1</anyType> <anyType xsi:type="xsd:int">2</anyType> <anyType xsi:type="xsd:int">3</anyType> </ArrayOfAnyType>
ファイルをストリームから読み込み、オブジェクトに変換します。
class Program { static void Main() { string fileName = "C:/sample.xml"; ClassName myClass; using( System.IO.TextReader reader = new System.IO.StreamReader( fileName ) ) { System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer( typeof( ClassName ) ); myClass = ( ClassName )serializer.Deserialize( reader ); } } }
逆シリアル化を行うためには、環境変数TEMPにより定義される一時フォルダに書き込むための、アクセス権が必要となります。