none
WCFサービスの実装クラスが複数ある場合の記述について RRS feed

  • 質問

  • 西脇です。

    みなさんのお知恵を拝借させてください。

    .NET Remotingでホストしていたサービスを、WCF に移行しようとしています。
    .NET Remoting の RemotingConfiguration.Configure メソッドのようなこと(以下サンプル)は、WCFでもできますでしょうか?



    using System;
    using System.Runtime.Remoting;

    namespace dotNetRemotingServer
    {
        class Program
        {
            static void Main(string[] args)
            {
                RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);

                Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.ApplicationName);
                Console.WriteLine("<Enter>で終了します。");
                Console.ReadLine();
            }
        }
    }


    条件

    ・構成ファイル(app.config)にWCF エンドポイントに関する構成設定を書きたい
    ・サービスの実装クラスが複数ある
    ・サービスの実装クラスが増えても WCFホストプロセスのコーディングを変えずに、構成ファイル(app.config)を書きかえるだけですませたい



    以上、よろしくお願い致します。

    2009年11月27日 7:41

回答

  • 素直に考えると、構成ファイルに記述してあるservice要素を参照してループすると思いますが。どうでしょう。

    ServiceModelSectionGroup serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(
                                        ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None));
    foreach (ServiceElement serviceElement in serviceModelSectionGroup.Services.Services)
    {
        ServiceHost host = new ServiceHost(System.Type.GetType(serviceElement.Name));
        host.Open();
    }


    私もサービス実装が複数ある理由には興味があるところですが
    既存の設計方式に大幅な修正が発生しないですむ。とかが理由なのかしらと想像。

    • 編集済み miromok 2009年11月30日 2:20 コード修正
    • 回答としてマーク 西脇 2009年11月30日 3:03
    2009年11月30日 2:18

すべての返信

  • こんにちは

    .NET Remoting は詳しくないのですが、 条件に書かれていることは、すべて可能ですよ。
    WCFは条件でかかれていることを構成ファイルで記述します。もちろんプログラム内で設定することもできますが。

    # 訂正
    最後の条件は、コントラクトを実装するクラスが複数の場合は、それごとにホストする必要があります。ひとつのクラスが複数のコントラクトを実装と勘違いしていました。すいません。
    • 編集済み handcraft 2009年11月28日 10:26
    2009年11月27日 14:18
  • 「サービスの実装クラスが複数ある」という記述が気になりました。
    WCFを起動させるためには、それぞれに対してServiceHostインスタンスを作成する必要があります。
    2009年11月28日 8:32
  • そうなんです。

    サービスの実装クラスが複数あって、それぞれに対してServiceHostインスタンスを作成するのならできるのですが、RemotingConfiguration.Configure みたく1行で書けないかなぁ・・・。
    そして、サービスの実装クラスが増えてもコーディングを変えずに、構成ファイル(app.config)を書きかえるだけですませたいなぁ・・・。

    という質問です。



    やっぱり、こう書くしかないですか。


    using System;
    using System.ServiceModel;

    namespace WcfServer
    {
        class Program
        {
            static void Main(string[] args)
            {
                ServiceHost host1 = new ServiceHost(typeof(WcfService1));
                ServiceHost host2 = new ServiceHost(typeof(WcfService2));
                ServiceHost host3 = new ServiceHost(typeof(WcfService3));
                host1.Open();
                host2.Open();
                host3.Open();

                Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.ApplicationName);
                Console.WriteLine("<Enter>で終了します。");
                Console.ReadLine();
            }
        }
    }

    2009年11月30日 0:33
  • そうなんです。

    サービスの実装クラスが複数ある場合、なのです。
    わかりにくくてすみません。


    以下のような構成ファイルのパターンです。


    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="NewBehavior1">
                        <serviceDebug httpHelpPageUrl="http://localhost:8087/WcfSercice1/help"
                            httpsHelpPageEnabled="false" />
                        <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8087/WcfSercice1/mex" />
                    </behavior>
                  <behavior name="NewBehavior2">
                    <serviceDebug httpHelpPageUrl="http://localhost:8087/WcfSercice2/help"
                        httpsHelpPageEnabled="false" />
                    <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8087/WcfSercice2/mex" />
                  </behavior>
                  <behavior name="NewBehavior3">
                    <serviceDebug httpHelpPageUrl="http://localhost:8087/WcfSercice3/help"
                        httpsHelpPageEnabled="false" />
                    <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8087/WcfSercice3/mex" />
                  </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="NewBehavior1" name="WcfServer.WcfSercice1">
                    <endpoint address="http://localhost:8087/WcfSercice1.svc" binding="basicHttpBinding"
                        bindingConfiguration="" contract="WcfServer.WcfSercice1" />
                </service>
                <service behaviorConfiguration="NewBehavior2" name="WcfServer.WcfSercice2">
                    <endpoint address="http://localhost:8087/WcfSercice2.svc" binding="basicHttpBinding"
                        bindingConfiguration="" contract="WcfServer.WcfSercice2" />
                </service>
                <service behaviorConfiguration="NewBehavior3" name="WcfServer.WcfSercice3">
                    <endpoint address="http://localhost:8087/WcfSercice3.svc" binding="basicHttpBinding"
                        bindingConfiguration="" contract="WcfServer.WcfSercice3" />
                </service>
            </services>
        </system.serviceModel>
    </configuration>
    2009年11月30日 0:42
  • なぜサービスを分けるのか、その辺りはちょっとわかりませんでした。

    質問の条件を満たしてはいないかもしれませんが、ヒントということで
    Windows プロセス アクティブ化サービスでのホスティング という方法があります。
    IISでのホストをもう少し一般化したものです。これを使うとアドレスを登録しておくとあとは自動的に起動されます。
    ただし、w3wp.exeというワーカープロセス内で動作します。逆に言うと、WCFをホストするためのWindows Serviceは不要です。(WCF以外の処理ができなくなるとも言います。)
    2009年11月30日 1:42
  • 素直に考えると、構成ファイルに記述してあるservice要素を参照してループすると思いますが。どうでしょう。

    ServiceModelSectionGroup serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(
                                        ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None));
    foreach (ServiceElement serviceElement in serviceModelSectionGroup.Services.Services)
    {
        ServiceHost host = new ServiceHost(System.Type.GetType(serviceElement.Name));
        host.Open();
    }


    私もサービス実装が複数ある理由には興味があるところですが
    既存の設計方式に大幅な修正が発生しないですむ。とかが理由なのかしらと想像。

    • 編集済み miromok 2009年11月30日 2:20 コード修正
    • 回答としてマーク 西脇 2009年11月30日 3:03
    2009年11月30日 2:18
  • なぜサービスを分けるのか・・・既存の.Net リモート処理の既存のクラスが3つに分かれていただけで、特に理由はありませんでした。
    これを1つにまとめてしまう、という手もありますね。

    盲点でした。


    Windows プロセス アクティブ化サービス (WAS) についても並行して調べています。
    開発中は、Windows XPで行うので使えませんが、最終的には、Windows Server 2008上で WAS を使う予定です。

    2009年11月30日 2:57
  • おお、これです。

    ServiceModelSectionGroup クラスで、serviceModel セクションを取得できるのですね。
    これを列挙して順番に ServiceHost インスタンスを作って、Open してやれば、目的のこと(サービスの実装クラスが増えても WCFホストプロセスのコーディングを変えずに、構成ファイル(app.config)を書きかえるだけですませたい)ができそうです。


    ありがとうございます。
    2009年11月30日 3:02