web-dev-qa-db-ja.com

複数のコントラクトでWCF ServiceHostを実行する

単一のコントラクトでServiceHostを実行すると、次のように正常に機能します。

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.Open();

次に、2番目(3番目、4番目、...)のコントラクトを追加します。私の最初の推測は、このようなエンドポイントを追加することです。

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();

ただし、ServiceHostの作成時にMyService1をパラメーターまたはMyService2として渡すことができるため、もちろんこれは機能しません-したがって、多くのエンドポイントをサービスに追加できますが、提供できるのはすべて同じコントラクトを使用する必要があるためです1つの実装?
ここでポイントを逃していると感じました。確かに、私が追加するすべてのエンドポイント契約に実装を提供する方法があるはずですか?

51
Sam

同じクラスに両方のサービス(インターフェース)を実装する必要があります。

servicehost = new ServiceHost(typeof(WcfEntryPoint));
servicehost.Open(); 

public class WcfEntryPoint : IMyService1, IMyService2
{
    #region IMyService1
    #endregion

    #region IMyService2
    #endregion
}

参考:ホストクラスコードを読みやすくするために、部分クラスを頻繁に使用します。

// WcfEntryPoint.IMyService1.cs
public partial class WcfEntryPoint : IMyService1
{
    // IMyService1 methods
}

// WcfEntryPoint.IMyService2.cs
public partial class WcfEntryPoint : IMyService2
{
    // IMyService2 methods
}
59
chilltemp

現在、私は同じ問題に直面しており、以下の実装を採用することにしました。このように多くのサービスコントラクトを使用することでパフォーマンスの問題があるかどうかはわかりませんが、最終的な実装では、おそらく10〜15のサービスコントラクト、つまり10〜15のServiceHostがあります。

私はすべてのWCFサービスを単一のWindowsサービス内でホストしています。

private void PublishWcfEndpoints()
{
    var mappings = new Dictionary<Type, Type>
    {
       {typeof (IAuthenticationService), typeof (AuthenticationService)},
       {typeof(IUserService), typeof(UserService)},
       {typeof(IClientService), typeof(ClientService)}
    };


    foreach (var type in mappings)
    {
        Type contractType = type.Key;
        Type implementationType = type.Value;

        ServiceHost serviceHost = new ServiceHost(implementationType);
        ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, ServiceHelper.GetDefaultBinding(),
                                                                  Properties.Settings.Default.ServiceUrl  + "/" + contractType.Name);
        endpoint.Behaviors.Add(new ServerSessionBehavior());

        ServiceDebugBehavior serviceDebugBehaviour =
            serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
        serviceDebugBehaviour.IncludeExceptionDetailInFaults = true;

        log.DebugFormat("Published Service endpoint: {0}", Properties.Settings.Default.ServiceUrl);

        serviceHost.Open();
        serviceHosts.Add(serviceHost);
    }

}

このタイプのセットアップについて、および特にパフォーマンス関連の問題がある場合は、お気軽にコメントしてください。

17
Saajid Ismail

この回答は、chilltempから受け入れられた回答のコメントに対するさらなる回答です。

サム、あなたは本当にあなたが10-50の契約を必要とする理由を決定し、別の解決策を見つけようとするべきです。 Juval LowyのWCF Coding Standards( http://www.idesign.net/ にあります)を調べたところ、次の参照が見つかりました。

3サービス契約... 4. 1人のメンバーとの契約を避けます。 5.サービス契約ごとに3〜5人のメンバーを持つように努めます。 6.サービス契約ごとに20人を超えるメンバーを入れないでください。おそらく12が実用上の制限です。

彼は契約の実装の制限については言及していません(私はそれを見つけることができます)が、ベストプラクティスに似たものとしてサービスの50の契約を見るとは想像できません。私が見つけた解決策の1つは、同様の機能にメンバー共有を使用することです。

たとえば、WCFサービスを使用して2つの値で数学を実行している場合、サービス側に4つのメンバーがある場合があります:Add(x、y)、Subtract(x、y)、Multiply(x、y)、Divide(x 、y)。これらをより一般的なメンバーに結合し、オブジェクトを使用して必要なデータを渡すと、メンバー数を簡単に減らしてスケーラビリティを高めることができます。例:PeformCalculation(obj)ここで、objにはx、y、およびaction(加算、減算、乗算、除算)プロパティがあります。

お役に立てれば。

10
Chris Porter

RoutingService クラスを使用して、この問題に対する別の解決策を見つけました。各コントラクトは、それ自体のServiceHostでホストする必要がありますが、それらのすべての上にRoutingServiceがあり、統一された「エンドポイント」で提示します。それについて codeproject article も書いています。サンプルコードは Bitbucket でも利用できます。

8
m0sa

チリの答えは、サービスで共有されている契約に問題がなければ機能します。それらを分離したい場合は、これを試してください:

Host1 = new ServiceHost(typeof(MyService1));
Host2 = new ServiceHost(typeof(MyService2));

Host1.Open();
Host2.Open();

public class MyService1 : IMyService1
{
    #region IMyService1
    #endregion
}

public class MyService2 : IMyService2
{
    #region IMyService2
    #endregion
}

編集:マットが投稿したように、これは各サービス/契約に複数のエンドポイントを必要とします

6
Chris Porter

誰もポイントを文書化していない。 1つ以上(グループとして、たとえばhttpなどの共通のURLから)を使用した場合は、同じバインディングインスタンス(それ以上ではない)を使用する必要があります。

あなたのサンプル:

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();

1つの新しいBinding()のみにする必要があります。httpでテストしました。

servicehost = new ServiceHost(typeof(MyService1));
 BasicHttpBinding binding = new BasicHttpBinding();
servicehost.AddServiceEndpoint(typeof(IMyService1),binding , "http://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), binding, "http://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();

少数のファイルで少数のコントラクトを実装する部分クラスに完全に同意します。

3
Jacek Cz

ベースアドレスとその下の複数のサービス/契約で分割するのはどうですか?私は今、developmachineの背後にいるのではなく、次のようなものです:

http:// myserver/myservices/serviceA
http:// myserver/myservices/serviceB
http:// myserver/myservices/serviceC

独自のServiceContractを実装する各サービス。

を変えることができます
public class WcfEntryPoint : IMyService1, IMyService2

public partial class WcfEntryPoint : IMyService1
public partial class WcfEntryPoint : IMyService2

1

私は何かを見逃しましたか、またはここで言及されていない最も簡単な解決策ですか?最も簡単な解決策は次のとおりです。Webサービスに複数のインターフェイスを使用しないでください。

しかし、それはインターフェースを分離できるという意味ではありません。これが、インターフェイスの継承がある理由です。

[ServiceContract]
public interface IMetaSomeObjectService : ISomeObjectService1, ISomeObjectService2
{
}

Metaインターフェイスは、他のすべてのインターフェイスを継承します。

[ServiceContract]
public interface ISomeOjectService1
{
    [OperationContract]
    List<SomeOject> GetSomeObjects();
}

[ServiceContract]
public interface ISomeOjectService2
{
    [OperationContract]
    void DoSomethingElse();
}

次に、サービスにはMetaインターフェイスのみがあります。

public class SomeObjectService : IMetaSomeObjectService
{
   public List<SomeOject> GetSomeObjects()
   {
       // code here
   }

   public void DoSomethingElse()
   {
       // code here
   }
}
0
Rhyous