// <summary>ソースコード：>IPCサービス登録</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;

namespace CommonMP.HYSSOP.OptionImpl.HSCommunicationTool.HyssopDotNetIpcTool
{
    /// <summary><para>class outline:</para>
    /// <para>IPCサービス登録</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/12/28][新規作成]</para>
    /// <para>本クラスは<see cref="IpcClientChannel"/>と<see cref="IpcClientChannel"/>を利用した簡易IPCを提供する。</para>
    /// </remarks>
    public static class HySIpcServiceRegister
    {
        /// <summary>
        /// サーバーチャネルオブジェクト
        /// </summary>
        private static IpcServerChannel m_csServerChannel;
        /// <summary>
        /// クライアントチャネルオブジェクト
        /// </summary>
        private static IpcClientChannel m_csClientChannel;
        /// <summary>
        /// ロックオブジェクト
        /// </summary>
        private static object m_csLock = new object();

        /// <summary>
        /// サーバーポート名フォーマット
        /// </summary>
        const string SERVER_PORT_NAME_FORMAT = "localhost:{0}";
        /// <summary>
        /// オブジェクトURI
        /// </summary>
        const string SERVER_OBJECT_URI = "HyssopIpcService";
        /// <summary>
        /// クライアントポートフォーマット
        /// </summary>
        const string CLIENT_PORT_NAME_FORMAT = "ipc://localhost:{0}/HyssopIpcService";

        /// <summary><para>method outline:</para>
        /// <para>サーバーポートを生成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIpcServiceRegister.CreateServerPort(csPortName, csType)</para>
        /// </example>
        /// <param name="csPortName">ポート名</param>
        /// <param name="csType">サーバとして公開する型</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>サーバープロセス側で実際に受信データを処理するオブジェクトの型情報を登録する。</para>
        /// </remarks>
        public static void CreateServerPort(string csPortName, Type csType)
        {
            lock (m_csLock)
            {
                if (m_csClientChannel == null)
                {
                    // サーバーチャネルを生成する
                    IpcServerChannel serverChannel = new IpcServerChannel(string.Format(SERVER_PORT_NAME_FORMAT, csPortName));

                    // サーバーチャネルを登録する
                    ChannelServices.RegisterChannel(serverChannel, false);

                    // 指定された型をリモートサービスとして公開する
                    //WellKnownObjectMode mode = WellKnownObjectMode.Singleton;
                    WellKnownObjectMode mode = WellKnownObjectMode.SingleCall;
                    RemotingConfiguration.RegisterWellKnownServiceType(csType, SERVER_OBJECT_URI, mode);

                    m_csServerChannel = serverChannel;
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>クライアントポートを生成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIpcServiceRegister.CreateClientPort(csPortName, csType)</para>
        /// </example>
        /// <param name="csRemotePortName">サーバの公開ポート名</param>
        /// <param name="csType">サーバの公開型</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>クライアントプロセス側からリモート呼び出しを行うオブジェクトの型情報を登録する。</para>
        /// </remarks>
        public static void CreateClientPort(string csRemotePortName, Type csType)
        {
            lock (m_csLock)
            {
                if (m_csClientChannel == null)
                {
                    // クライアントチャネル生成
                    IpcClientChannel clientChannel = new IpcClientChannel();

                    // クライアントチャネルを登録する
                    ChannelServices.RegisterChannel(clientChannel, false);

                    m_csClientChannel = clientChannel;
                }
            }
            // リモートアクセスするオブジェクトを登録する
            string objectUri = string.Format(CLIENT_PORT_NAME_FORMAT, csRemotePortName);
            WellKnownClientTypeEntry remoteType = new WellKnownClientTypeEntry(csType, objectUri);
            RemotingConfiguration.RegisterWellKnownClientType(remoteType);

        }

        /// <summary><para>method outline:</para>
        /// <para>サーバーポートを削除する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIpcServiceRegister.DeleteServerPort()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para><see cref="CreateServerPort"/>で登録したサーバーポートを削除する。</para>
        /// </remarks>
        public static void DeleteServerPort()
        {
            lock (m_csLock)
            {
                if (m_csServerChannel != null)
                {
                    ChannelServices.UnregisterChannel(m_csServerChannel);
                    m_csServerChannel = null;
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>クライアントポートを削除する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIpcServiceRegister.DeleteClientPort()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para><see cref="CreateClientPort"/>で登録したサーバーポートを削除する。</para>
        /// </remarks>
        public static void DeleteClientPort()
        {
            lock (m_csLock)
            {
                if (m_csClientChannel != null)
                {
                    ChannelServices.UnregisterChannel(m_csClientChannel);
                    m_csClientChannel = null;
                }
            }
        }
    }
}
