51

単一のコントラクトで 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つの実装?
ここで、私は要点を見逃していると感じました。私が追加するすべてのエンドポイント コントラクトの実装を提供する何らかの方法があるはずです。

4

8 に答える 8

61

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

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
}
于 2008-12-02T16:22:32.503 に答える
17

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

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

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);
    }

}

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

于 2009-08-17T16:39:37.370 に答える
10

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

サム、なぜ 10 ~ 50 の契約が必要なのかを判断し、別の解決策を見つける必要があります。Juval Lowy の WCF コーディング標準 ( 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、およびアクション (加算、減算、乗算、除算) プロパティがあります。

お役に立てれば。

于 2008-12-03T17:37:34.113 に答える
9

RoutingServiceクラスを使用して、この問題の別の解決策を見つけました。各コントラクトは引き続き独自の でホストする必要ServiceHostがありますが、RoutingServiceそれらすべての上に座って、統一された「エンドポイント」を介してそれらを提示することができます。それについてのコードプロジェクトの記事も書いています。サンプル コードはBitbucketでも入手できます。

于 2012-02-29T23:46:19.130 に答える
6

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

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
}

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

于 2008-12-02T16:44:41.833 に答える
3

文書化されたエンドポイントはありません。複数の (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();

私は 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();

いくつかのファイルにいくつかのコントラクトを実装する部分クラスに完全に同意します。

于 2015-09-19T08:05:43.447 に答える
1

ベースアドレスとその下の複数のサービス/契約で分割するのはどうですか?私は現在、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

于 2009-08-19T09:49:24.293 に答える
0

私は何かを見逃していましたか、それともここで言及されていない最も簡単な解決策ですか? 最も簡単な解決策は次のとおりです。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
   }
}
于 2016-06-15T16:38:26.800 に答える