前回はジェネリックなインタフェースを、サービスクラスが直接実装していました。
今回は、サービスのベースクラスを用意し、インタフェースをベースクラスに実装させてみます。サービスクラスとインタフェースとの間に、クラス階層を1つ挟む形です。
まずは、データコントラクト、サービスコントラクト、ベースクラス、サービスクラスを作成します。
[DataContract] public class Customer { [DataMember] public string Code { get; set; } [DataMember] public string Name { get; set; } } // マスターデータを返すサービスのコントラクト [ServiceContract] public interface IMasterService<T> where T : class { [OperationContract] T GetData(string code); } // ベースクラスを間に挟んでみる public abstract class MasterService<T> : IMasterService<T> where T : class { public abstract T GetData(string code); } // ベースクラスから派生してサービスを実装 public class CustomerService : MasterService<Customer> { public override Customer GetData(string code) { return new Customer() { Code = code, Name = "test" }; } }
これらのクラスを使って、サービス起動から呼び出しまで行ったコードが下になります。前回とほぼ同じですがw
class Program { static void Main(string[] args) { // サービス起動 string address = "net.tcp://localhost:8000/CustomerService"; ServiceHost host = new ServiceHost(typeof(CustomerService)); host.AddServiceEndpoint( typeof(IMasterService<Customer>), new NetTcpBinding(), address); host.Open(); // サービス呼び出し IMasterService<Customer> channel = ChannelFactory<IMasterService<Customer>>.CreateChannel( new NetTcpBinding(), new EndpointAddress(address)); Customer data = channel.GetData("0001"); Console.WriteLine("{0}:{1}", data.Code, data.Name); ((IChannel)channel).Close(); Console.WriteLine("Enter で終了します。"); Console.ReadLine(); host.Close(); } }
このサンプルコードを実行したときの、スクリーンショットは下の通りです。
サービスの呼び出しに成功していますね。
WCF の調査の為に海外のブログを見ていたとき、「ジェネリックなベースは使えない」みたいなコメントがあったので、実際に試してみました。昔は動かなかったのでしょうか?