今回は、データコントラクトの基本について。
WCFでは、ユーザ定義型などをサービスでやり取りするには
データコントラクトとして定義します。
WCFでは、DataContractSerializerを利用してデータをシリアライズ/デシリアライズします。
データコントラクトとして定義するには、以下のようにします。
- クラスにDataContract属性を付与
- 公開したいデータに対して、DataMember属性を付与
DataContractSerializerは、WCFが内部で利用する
通常は開発者が意識する必要はありません。
DataContractSerializerには、以下の決まり事があります。
- DataContract属性が付与されている場合はマークされているメンバーが対象となる。
- DataContract属性が付与されていない場合は公開されているメンバーが全て対象となる。
- デフォルトコンストラクタを持つクラスのみが対象。
以下の型に関しては、暗黙でデータコントラクトとして利用できます。
- パラメータを持たないコンストラクタを持つ型
- コレクション型
- CollectionDataContract属性を付与できるが必須ではない。
- 列挙型
- プリミティブ型
上記の事から、普通にクラス定義し、内部でプロパティとして
宣言しているデータの型がstringとかDateTimeとかの場合は
DataContract属性を付与しなくても利用できるということになります。
以下、サンプルです。
サンプルでは、サービスメソッドを2つ定義し
一つはDataContractを付与したクラス。もう一つはDataContractを付与していないクラスを
利用しています。
まず、サービス定義。
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { [ServiceContract] public interface IMyService { /// <summary> /// DataContract属性を付与したクラスを利用. /// </summary> [OperationContract] MyData GetMyData(); /// <summary> /// DataContract属性を付与していないクラスを利用. /// </summary> [OperationContract] MyData2 GetMyData2(); } }
using System; using System.Collections.Generic; using System.Linq; namespace Gsf.Samples.WCF { public class MyService : IMyService { public MyData GetMyData() { return new MyData { Value1 = "MyData Value1" ,Value2 = 999 ,Items = new List<MyItem> { new MyItem { Value3 = DateTime.Now } ,new MyItem { Value3 = DateTime.Now.AddMonths(-1) } } }; } public MyData2 GetMyData2() { return new MyData2 { Value1 = "MyData2 Value1" ,Value2 = 998 ,Items = new List<MyItem2> { new MyItem2 { Value3 = DateTime.Now } ,new MyItem2 { Value3 = DateTime.Now.AddMonths(-1) } } }; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; namespace Gsf.Samples.WCF { [DataContract] public class MyData { [DataMember] public string Value1 { get; set; } [DataMember] public int Value2 { get; set; } [DataMember] public IEnumerable<MyItem> Items { get; set; } } } using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; namespace Gsf.Samples.WCF { [DataContract] public class MyItem { [DataMember] public DateTime Value3 { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; namespace Gsf.Samples.WCF { public class MyData2 { public string Value1 { get; set; } public int Value2 { get; set; } public IEnumerable<MyItem2> Items { get; set; } } } using System; using System.Collections.Generic; using System.Linq; namespace Gsf.Samples.WCF { public class MyItem2 { public DateTime Value3 { get; set; } } }
次にホストアプリ。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace Gsf.Samples.WCF { class Program { static void Main() { using (var host = new ServiceHost(typeof(MyService))) { host.Open(); Console.WriteLine("サービスが開始されました。"); Console.WriteLine("press <ENTER> to exit..."); Console.ReadLine(); host.Close(); } } } }
ホスト側のアプリケーション構成ファイル。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="Gsf.Samples.WCF.MyService"> <host> <baseAddresses> <add baseAddress="http://localhost:8088/WCFSample008/MyService"/> </baseAddresses> </host> <endpoint address="" binding="basicHttpBinding" contract="Gsf.Samples.WCF.IMyService" /> </service> </services> </system.serviceModel> </configuration>
次にクライアントアプリ。
クライアント側ではPropertyGridが2枚配置してあり
それぞれのデータを表示するようになっています。
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using Gsf.Samples.WCF.MyServiceRef; namespace Gsf.Samples.WCF { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { prpMyData.SelectedObject = null; prpMyData2.SelectedObject = null; ActiveControl = btnCallServiceMethod; } private void btnCallServiceMethod_Click(object sender, EventArgs e) { using (var client = new MyServiceRef.MyServiceClient()) { // DataContract属性を付与したデータを取得. MyData data = client.GetMyData(); prpMyData.SelectedObject = data; // DataContract属性を付与していないデータを取得. MyData2 data2 = client.GetMyData2(); prpMyData2.SelectedObject = data2; } } } }
クライアント側のアプリケーション構成ファイル。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="http://localhost:8088/WCFSample008/MyService" binding="basicHttpBinding" contract="MyServiceRef.IMyService" /> </client> </system.serviceModel> </configuration>
実行すると以下のようになります。どちらの場合にもデータが取得できています。
サンプルは以下の場所にアップしてあります。
https://sites.google.com/site/gsfzero1/Home/WCFSample-008.zip?attredirects=0&d=1
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ