ジェネリックなベースクラスから派生したサービスは使えるか?

前回はジェネリックなインタフェースを、サービスクラスが直接実装していました。

今回は、サービスのベースクラスを用意し、インタフェースをベースクラスに実装させてみます。サービスクラスとインタフェースとの間に、クラス階層を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();
    }
}

このサンプルコードを実行したときの、スクリーンショットは下の通りです。

f:id:griefworker:20090728102552p:image

サービスの呼び出しに成功していますね。

WCF の調査の為に海外のブログを見ていたとき、「ジェネリックなベースは使えない」みたいなコメントがあったので、実際に試してみました。昔は動かなかったのでしょうか?