Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

【C#】任意のXMLを読み込めるクラスXmlLoaderをつくってみた

この記事は、C# Advent Calendarの22日目です。

qiita.com

任意のXMLを読み込めるクラスXmlLoaderをつくってみました。

開発/動作環境

Visual Studio 2015、.NET Framework4.6

ソースコード

XmlLoader.cs

using System;
using System.IO;
using System.Xml.Serialization;

namespace Infrastructure {
    /// <summary>
    /// XMLファイルを読み込む機能を提供します。
    /// </summary>
    /// <typeparam name="T">
    /// 読み込むデータを設定するオブジェクトの型。この型には、デシリアライズできるように
    /// <see cref="System.Xml.Serialization"/>名前空間の属性を付与する必要があります。
    /// </typeparam>
    public class XmlLoader<T> {
        /// <summary>
        /// XMLファイルを読み込みます。
        /// </summary>
        /// <returns>読み込んだデータを設定したオブジェクト。</returns>
        public T Load(string xmlFileFulllName) {
            if (string.IsNullOrWhiteSpace(xmlFileFulllName))
                throw new ArgumentException("XMLファイルのパスを指定してください。", nameof(xmlFileFulllName));

            if (File.Exists(xmlFileFulllName) == false)
                throw new FileNotFoundException("指定されたXMLファイルは存在しません。", xmlFileFulllName);

            using (FileStream stream = new FileStream(xmlFileFulllName, FileMode.Open, FileAccess.Read)) {
                return this.Load(stream);
            }
        }

        /// <summary>
        /// XMLのストリームを読み込みます。
        /// </summary>
        /// <returns>読み込んだデータを設定したオブジェクト。</returns>
        public T Load(Stream xmlStream) {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            return (T) serializer.Deserialize(xmlStream);
        }
    }
}

動作確認

試しに、app.configを読み込んでみます。

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings file=".\hoge.xml">
        <add key="Foo" value="FooValue"/>
        <add key="Bar" value="BarValue"/>
    </appSettings>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
    </startup>
</configuration>

まず、読み込んだデータを格納するデータクラスを作ります。

データクラス

データクラスは、Visual Studioの「XMLをクラスとして貼り付ける」機能を使って自動生成しました。ちゃんとSystem.Xml.Serialization名前空間の属性も付けてくれます。
書き足したのは、ToStringだけです。

nameuntitled.hatenablog.com

using System.Linq;
using System.Text;

namespace Infrastructure {

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class configuration {

        private configurationAppSettings appSettingsField;

        private configurationStartup startupField;

        /// <remarks/>
        public configurationAppSettings appSettings {
            get {
                return this.appSettingsField;
            }
            set {
                this.appSettingsField = value;
            }
        }

        /// <remarks/>
        public configurationStartup startup {
            get {
                return this.startupField;
            }
            set {
                this.startupField = value;
            }
        }

        public override string ToString() {
            StringBuilder b = new StringBuilder();
            b.Append("configuration ");
            b.AppendFormat("appSettings:[{0}] ", this.appSettings).AppendLine();
            b.AppendFormat("startup:[{0}] ", this.startup);

            return b.ToString();
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class configurationAppSettings {

        private configurationAppSettingsAdd[] addField;

        private string fileField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("add")]
        public configurationAppSettingsAdd[] add {
            get {
                return this.addField;
            }
            set {
                this.addField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string file {
            get {
                return this.fileField;
            }
            set {
                this.fileField = value;
            }
        }

        public override string ToString() {
            StringBuilder b = new StringBuilder();
            b.Append("appSettings ");
            b.AppendFormat("file:[{0}] ", this.file);
            b.Append(string.Join(",", this.add.AsEnumerable()));

            return b.ToString();
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class configurationAppSettingsAdd {

        private string keyField;

        private string valueField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string key {
            get {
                return this.keyField;
            }
            set {
                this.keyField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string value {
            get {
                return this.valueField;
            }
            set {
                this.valueField = value;
            }
        }

        public override string ToString() {
            StringBuilder b = new StringBuilder();
            b.Append("add ");
            b.AppendFormat("key:[{0}] ", this.key);
            b.AppendFormat("value:[{0}] ", this.value);

            return b.ToString();
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class configurationStartup {

        private configurationStartupSupportedRuntime supportedRuntimeField;

        /// <remarks/>
        public configurationStartupSupportedRuntime supportedRuntime {
            get {
                return this.supportedRuntimeField;
            }
            set {
                this.supportedRuntimeField = value;
            }
        }

        public override string ToString() {
            StringBuilder b = new StringBuilder();
            b.Append("startup ");
            b.AppendFormat("supportedRuntime:[{0}] ", this.supportedRuntime);

            return b.ToString();
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class configurationStartupSupportedRuntime {

        private string versionField;

        private string skuField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string version {
            get {
                return this.versionField;
            }
            set {
                this.versionField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string sku {
            get {
                return this.skuField;
            }
            set {
                this.skuField = value;
            }
        }
        public override string ToString() {
            StringBuilder b = new StringBuilder();
            b.Append("supportedRuntime ");
            b.AppendFormat("version:[{0}] ", this.version);
            b.AppendFormat("sku:[{0}] ", this.sku);

            return b.ToString();
        }
    }
}

Program.cs

読み込む処理をMainに記述します。

using System;

namespace Infrastructure {
    class Program {
        static void Main(string[] args) {
            configuration c = new XmlLoader<configuration>().Load(@"C:\Sandbox\app.config");
            Console.WriteLine(c);

            Console.ReadKey();
        }
    }
}

動作結果

f:id:JHashimoto:20151221225243p:plain

ちゃんと読み込めていることが確認できました。