The Backyard - XmlForDataExchange Diff
- Added parts are displayed like this.
- Deleted parts are displayed
like this.
この記事は、「WEB+DB PRESS Vol.14」(技術評論社)に掲載していただいた記事の元原稿(必要に応じて加筆/修正/削除をしています)を公開するものです。
!XMLをデータ交換に利用する
クライアントとサーバーのインターフェイスを考えた場合、SOAP(XML Webサービス)が有力な手段であることは間違いありません。しかし、ASP.NETでの実装が容易だからとメソッドを意識し過ぎた設計を行うとクライアントとサーバー間の通信が不必要に増加してしまう可能性があります(図 webcs.png)。また、本来静的な情報提供をサービスとして実装することは、不要な開発を行うことにも通じます。
たとえばNetLauncherがWebサーバーから取得する情報は、
*登録されている(実行が許可されている)アプリケーションのリスト
*アプリケーションを構成するアセンブリ
ですが、いずれも静的な情報として配置可能です。
これに対して、サーバー側にXML Webサービスを実装し、String[] GetApplicationNames()、Uri GetApplicationLocation(String appName)……といったメソッドを提供するのはそれほど得策ではありません。このような処理には、Webサービスを実装するのではなく、単なるファイルサーバーとしてWebサーバーを利用するのが望ましいと言えます。
同様に、既にPC上にExcelなどで作成した検証済みデータが存在するのであれば、メソッドを対話的に呼び出す設計とはせずに、データ全体をまとめて転送しサーバー側で一括処理を行うように設計すべきです。Webアプリケーションと異なり、スマートクライアントであれば非同期通信をビジネスルールとして記述できるため、それによって長時間応答待ちとなるというようなことは無いからです。
!XmlSerializerを利用したXMLの読み込み
最初に構成ファイルの定義を行いましょう。特に理由がない限り、アプリケーションで使用するパラメータファイルは、特別なツール無しに編集可能で、かつプログラムでの操作が容易な形式を選択すべきです。.NET Frameworkでこの条件に合うファイル形式はXMLです。XMLはテキストですので、いざとなったらメモ帳で編集できますし、XmlSerializerを利用すれば、オブジェクトとの相互変換も可能です。
次のリストは、NetLauncherが構成ファイルを読み込む部分です(WebLauncher.cs:ReadConfigメソッド)。
リスト:WebLauncher.cs:ReadConfigメソッド(抜粋)
FileStream stm = configProxy.InputStream;
try
{
System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(typeof(applicationList));
configFile = (applicationList)serializer.Deserialize(stm);
}
catch (Exception e)
{
throw new ConfigurationException(e.Message, e);
}
finally
{
stm.Close();
}
configProxyはWebFileのインスタンスで、構成ファイルを保持しています。ここからFileStreamを取得し、XmlSerializerのDeserializeメソッドを利用して、applicationListのインスタンスを生成しています。例外処理を記述しているため多少かさばっていますが、純粋な読み込みとパーシングはXmlSerializerのDeserializeメソッドの呼び出しの1行だけで完了しています。
ここでXmlSerializerを生成している5行目に注目してください。XmlSerializerのコンストラクタに生成すべきクラスをtypeof(applicationList)として与えています。XmlSerializerはコンストラクタで与えられたクラスとXMLの相互変換を行うクラスなのです。リストのようにXMLからオブジェクトを生成するにはDeserializeメソッドを使用し、逆にオブジェクトをXMLにするにはSerializeメソッドを使用します。ただし、XmlSerializerで処理可能なクラスには特殊な属性を与える必要があります。このようなクラスを作成するには、XMLスキーマを定義しスキーマコンパイラに自動生成させるのが常道です。
VS.NETにはXMLスキーマエディターが組み込まれているため、プロジェクトの追加でXMLスキーマを選択すると簡便にスキーマを作成できます(EditSchema.png)。NetLauncherでは、applicationListをルート要素として、異常時のEメール送信用パラメータ(contact要素)、1以上のサーバーと構成ファイルのパス情報(host要素)、0以上のアプリケーション情報(application要素)を格納したXMLとして構成ファイルを定義しました。ここで、application要素を0以上としているのは、インストール時点ではサーバーの情報だけを格納しておき、サーバーから実際の構成ファイルを取得すれば良いからです。
リスト:applicationList.xsd(抜粋)
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema targetNamespace="http://gihyo.co.jp/wdpress/appList.xsd" ...省略...>
<xs:element name="applicationList">
<xs:complexType>
<xs:sequence>
<xs:element name="contact" type="ContactType" />
<xs:element name="host" type="HostType"
maxOccurs="unbounded" minOccurs="1" />
<xs:element name="application" type="ApplicationType"
maxOccurs="unbounded" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
...省略...
</xs:schema>
このようにして作成したXMLスキーマ(以降XSD)をスキーマコンパイラを利用してクラスファイルに変換します(リスト:applicationList.cs)。
リスト:applicationList.cs(抜粋)
...省略...
//
// このソース コードは xsd によって自動生成されました。 Version=1.0.3705.288 です。
//
using System.Xml.Serialization;
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://gihyo.co.jp/wdpress/appList.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://gihyo.co.jp/wdpress/appList.xsd", IsNullable=false)]
public class applicationList {
/// <remarks/>
public ContactType contact;
...省略...
.NET FrameworkのスキーマコンパイラはXSD.EXEという名称で、デフォルトでC:\Program Files\Microsoft.NET\FrameworkSDK\Binディレクトリにインストールされます。XSD.EXEはここに示したXSDからC#のクラスの生成以外にも、VB.NETのクラスの生成や、逆にアセンブリからXSDを生成する機能も提供しています。
なおVS.NETでXMLスキーマを扱う場合、注意点が1つあります。デフォルトの状態ではXSDとスキーマコンパイラが関連付けされていないのです。そのため、VS.NETのツールメニューにXSD.EXEを登録したほうが良いでしょう(RegisterSchemaCompiler.png)。このように登録しておけば、ソリューションエクスプローラでXSDを選択してスキーマコンパイラを実行することによりクラスファイルの生成が行われるようになります。
後は生成したクラスのソースファイルを、プロジェクトの既存項目の追加を利用して登録すれば完了です。
!XMLをデータ交換に利用する
クライアントとサーバーのインターフェイスを考えた場合、SOAP(XML Webサービス)が有力な手段であることは間違いありません。しかし、ASP.NETでの実装が容易だからとメソッドを意識し過ぎた設計を行うとクライアントとサーバー間の通信が不必要に増加してしまう可能性があります(図 webcs.png)。また、本来静的な情報提供をサービスとして実装することは、不要な開発を行うことにも通じます。
たとえばNetLauncherがWebサーバーから取得する情報は、
*登録されている(実行が許可されている)アプリケーションのリスト
*アプリケーションを構成するアセンブリ
ですが、いずれも静的な情報として配置可能です。
これに対して、サーバー側にXML Webサービスを実装し、String[] GetApplicationNames()、Uri GetApplicationLocation(String appName)……といったメソッドを提供するのはそれほど得策ではありません。このような処理には、Webサービスを実装するのではなく、単なるファイルサーバーとしてWebサーバーを利用するのが望ましいと言えます。
同様に、既にPC上にExcelなどで作成した検証済みデータが存在するのであれば、メソッドを対話的に呼び出す設計とはせずに、データ全体をまとめて転送しサーバー側で一括処理を行うように設計すべきです。Webアプリケーションと異なり、スマートクライアントであれば非同期通信をビジネスルールとして記述できるため、それによって長時間応答待ちとなるというようなことは無いからです。
!XmlSerializerを利用したXMLの読み込み
最初に構成ファイルの定義を行いましょう。特に理由がない限り、アプリケーションで使用するパラメータファイルは、特別なツール無しに編集可能で、かつプログラムでの操作が容易な形式を選択すべきです。.NET Frameworkでこの条件に合うファイル形式はXMLです。XMLはテキストですので、いざとなったらメモ帳で編集できますし、XmlSerializerを利用すれば、オブジェクトとの相互変換も可能です。
次のリストは、NetLauncherが構成ファイルを読み込む部分です(WebLauncher.cs:ReadConfigメソッド)。
リスト:WebLauncher.cs:ReadConfigメソッド(抜粋)
FileStream stm = configProxy.InputStream;
try
{
System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(typeof(applicationList));
configFile = (applicationList)serializer.Deserialize(stm);
}
catch (Exception e)
{
throw new ConfigurationException(e.Message, e);
}
finally
{
stm.Close();
}
configProxyはWebFileのインスタンスで、構成ファイルを保持しています。ここからFileStreamを取得し、XmlSerializerのDeserializeメソッドを利用して、applicationListのインスタンスを生成しています。例外処理を記述しているため多少かさばっていますが、純粋な読み込みとパーシングはXmlSerializerのDeserializeメソッドの呼び出しの1行だけで完了しています。
ここでXmlSerializerを生成している5行目に注目してください。XmlSerializerのコンストラクタに生成すべきクラスをtypeof(applicationList)として与えています。XmlSerializerはコンストラクタで与えられたクラスとXMLの相互変換を行うクラスなのです。リストのようにXMLからオブジェクトを生成するにはDeserializeメソッドを使用し、逆にオブジェクトをXMLにするにはSerializeメソッドを使用します。ただし、XmlSerializerで処理可能なクラスには特殊な属性を与える必要があります。このようなクラスを作成するには、XMLスキーマを定義しスキーマコンパイラに自動生成させるのが常道です。
VS.NETにはXMLスキーマエディターが組み込まれているため、プロジェクトの追加でXMLスキーマを選択すると簡便にスキーマを作成できます(EditSchema.png)。NetLauncherでは、applicationListをルート要素として、異常時のEメール送信用パラメータ(contact要素)、1以上のサーバーと構成ファイルのパス情報(host要素)、0以上のアプリケーション情報(application要素)を格納したXMLとして構成ファイルを定義しました。ここで、application要素を0以上としているのは、インストール時点ではサーバーの情報だけを格納しておき、サーバーから実際の構成ファイルを取得すれば良いからです。
リスト:applicationList.xsd(抜粋)
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema targetNamespace="http://gihyo.co.jp/wdpress/appList.xsd" ...省略...>
<xs:element name="applicationList">
<xs:complexType>
<xs:sequence>
<xs:element name="contact" type="ContactType" />
<xs:element name="host" type="HostType"
maxOccurs="unbounded" minOccurs="1" />
<xs:element name="application" type="ApplicationType"
maxOccurs="unbounded" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
...省略...
</xs:schema>
このようにして作成したXMLスキーマ(以降XSD)をスキーマコンパイラを利用してクラスファイルに変換します(リスト:applicationList.cs)。
リスト:applicationList.cs(抜粋)
...省略...
//
// このソース コードは xsd によって自動生成されました。 Version=1.0.3705.288 です。
//
using System.Xml.Serialization;
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://gihyo.co.jp/wdpress/appList.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://gihyo.co.jp/wdpress/appList.xsd", IsNullable=false)]
public class applicationList {
/// <remarks/>
public ContactType contact;
...省略...
.NET FrameworkのスキーマコンパイラはXSD.EXEという名称で、デフォルトでC:\Program Files\Microsoft.NET\FrameworkSDK\Binディレクトリにインストールされます。XSD.EXEはここに示したXSDからC#のクラスの生成以外にも、VB.NETのクラスの生成や、逆にアセンブリからXSDを生成する機能も提供しています。
なおVS.NETでXMLスキーマを扱う場合、注意点が1つあります。デフォルトの状態ではXSDとスキーマコンパイラが関連付けされていないのです。そのため、VS.NETのツールメニューにXSD.EXEを登録したほうが良いでしょう(RegisterSchemaCompiler.png)。このように登録しておけば、ソリューションエクスプローラでXSDを選択してスキーマコンパイラを実行することによりクラスファイルの生成が行われるようになります。
後は生成したクラスのソースファイルを、プロジェクトの既存項目の追加を利用して登録すれば完了です。