wcf

今になってようやくWCFをいじってみる。
最初の目標は
・configファイルは使わない(プログラムで全てやりきる)
・プロキシ生成ツールも使わない(プログラムで全てやりきる)
・RemotingのCAO相当の機能も試す
この三つ。

できたコードはコレ。
Service。参照設定でSystem.ServiceModelを参照

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;


namespace Service
{
    [ServiceContract]
    public interface IStatelessService
    {
        [OperationContract]
        string GetDatetime(string data);
    }

    public class StatelessServiceImpl
        :IStatelessService
    {
        private string data_;
        public string GetDatetime(string data)
        {
            data_ += data;
            Console.WriteLine(data_);
            Console.WriteLine("StatelessServiceImpl GetDatetime called");
            return DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
        }
    }


    [ServiceContract(SessionMode=SessionMode.Required)]
    public interface IstatefulService
    {
        [OperationContract]
        void SetName(string name);

        [OperationContract]
        string GetName();
    }

    [ServiceBehavior(
        ConcurrencyMode = ConcurrencyMode.Single,
        InstanceContextMode = InstanceContextMode.PerSession)]
    public class statefulServiceImpl
    :IstatefulService,IDisposable
    {
        private string name_;

        public void SetName(string name)
        {
            Console.WriteLine("statefulServiceImpl SetName called");

            name_ = name;
        }

        public string GetName()
        {
            Console.WriteLine("statefulServiceImpl GetName called");

            return name_;
        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}

Server。参照設定でSystem.ServiceModelを参照。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;

namespace Server
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Uri statelessSvcEndpoint = new Uri("net.tcp://localhost:8000/stateless");
                ServiceHost statelessSvcHost = new ServiceHost(typeof(Service.StatelessServiceImpl), statelessSvcEndpoint);

                statelessSvcHost.AddServiceEndpoint(
                    typeof(Service.IStatelessService),
                    new NetTcpBinding(),
                    "StatelessService.svc");

                //ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                //smb.HttpGetEnabled = true;
                //statelessSvcHost.Description.Behaviors.Add(smb);

                statelessSvcHost.Open();

                Console.WriteLine("start stateless svc");

                statelessSvcHost.ChannelDispatchers.ToList().ForEach(
                    c => Console.WriteLine(c.Listener.Uri));

                Uri statefulSvcEndpoint = new Uri("net.tcp://localhost:8000/stateful");
                ServiceHost statefulSvcHost = new ServiceHost(typeof(Service.statefulServiceImpl), statefulSvcEndpoint);

                statefulSvcHost.AddServiceEndpoint(
                    typeof(Service.IstatefulService),
                    new NetTcpBinding(),
                    "StatefulService.svc");

                statefulSvcHost.Open();

                Console.WriteLine("start stateful svc");

                statefulSvcHost.ChannelDispatchers.ToList().ForEach(
                    c => Console.WriteLine(c.Listener.Uri));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.ReadLine();
        }
    }
}


Client。参照設定でSystem.ServiceModelを参照。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {

                Console.WriteLine("stateless service呼び出し");
                EndpointAddress statelessSvcEp = new EndpointAddress("net.tcp://localhost:8000/stateless/StatelessService.svc");

                ChannelFactory statelessSvcFac =
                    new ChannelFactory(new NetTcpBinding(), statelessSvcEp);

                Service.IStatelessService statelessSvc = statelessSvcFac.CreateChannel();

                Console.WriteLine(statelessSvc.GetDatetime(DateTime.Now.ToString("HH:mm:ss")));
                Console.WriteLine(statelessSvc.GetDatetime(DateTime.Now.ToString("HH:mm:ss")));

                Console.WriteLine("stateful service呼び出し");
                EndpointAddress statefulSvcEp = new EndpointAddress("net.tcp://localhost:8000/stateful/StatefulService.svc");

                ChannelFactory statefulSvcFac =
                    new ChannelFactory(new NetTcpBinding(), statefulSvcEp);

                Service.IstatefulService statefulSvc = statefulSvcFac.CreateChannel();

                statefulSvc.SetName("太郎");
                Console.WriteLine(statefulSvc.GetName());
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.ReadLine();
        }
    }
}

デフォルトではSingletonみたい。
RemotingのInitializeLifetimeServiceでreturn nullしてたみたいに、何かしないとインスタンスがどこかで消えちゃうかもしれない。
(調べてない)

RemotingだとChannelも公開するタイプもプロセス毎(ホントはAppDomain)になっちゃうのがイヤだったけど、WCFではそういうことはなさそう。
コレいいな・・・。