2016-04-07 6 views
1

私は完全に異なる依存関係と全く異なる責任を持っている2つの完全に別々のサービス(契約に沿って)を持っています。しかし、彼らは共通して得たものがあります:彼らは、彼らが同じ結合/輸送に 1つのサービスホスト内で複数のサービスをホストしていますか?

ダミーの契約を持っている彼らは、同じベースアドレス

  • を共有
  • 一緒に閉じ/オープンする

    • 必要:

      public class IFoo { 
          void Foo(); 
      } 
      
      public class IBar { 
          void Bar(); 
      } 
      

      ここでは、両方を同じサービスホストにホストすることです。

      public class FooImpl : IFoo { } 
      
      public class BarImpl : IBar { } 
      
      var host = new ServiceHost(); 
      host.AddEndpoint(typeof(FooImpl); 
      host.AddEndpoint(typeof(BarImpl); 
      host.Open(); 
      
      :私はこのような何かをする方法を探していますが

      public class FooBar : IFoo, IBar { } 
      
      var host = new ServiceHost(typeof(FooBar)); 
      

      :私はそれをエンドポイントとして、両方のサービスを公開し、このように同じサービスタイプでそれらを実装することが可能だということを認識しています

      私は、サービスの実装を素敵できちんとした状態に保つことができます。それぞれは、すべてのための神オブジェクトではなく、独自の依存関係を持ちます。

      誰でもこれを達成する方法について考えていますか?

  • +0

    同じServiceHostで両方のサービスをホストする必要がありますか、それぞれ独自のサービスとエンドポイントを持つ複数のServiceHostインスタンスを受け入れることはできますか? –

    +0

    @WicherVisser残念なことに、すべてのサービスが同じポートで実行される必要があるためです。 – artganify

    +0

    複数の契約を持つWCF ServiceHostを実行する可能性があります(http://stackoverflow.com/questions/334472/run-wcf-servicehost-with-multiple-contracts) –

    答えて

    4

    それぞれ独自のサービスとエンドポイントを持つ複数のServiceHostをホストすることができ、すべて同じベースアドレスとポートを共有します。ここでServiceHostingクラスにカプセル化された、私の実装です:

    public class ServiceHosting<T1, T2> 
    { 
        //Declaration 
        protected ServiceHost SelfHost; 
        protected string BaseUrlString; 
        protected int Port; 
        protected string HostUrlString = ""; 
        protected bool ExtendedBinding; 
    
        //Constructor 
        public ServiceHosting(string url, int port, bool extendedBinding = false) 
        { 
         BaseUrlString = url; 
         Port = port; 
         ExtendedBinding = extendedBinding; 
        } 
    
        //Properties 
        protected int Max => int.MaxValue; 
    
        public virtual bool StartService(int port) 
        { 
         try 
         { 
          var hostName = System.Net.Dns.GetHostName(); 
    
          HostUrlString = [email protected]"net.tcp://{hostName}:{port}{BaseUrlString}"; //GM 10.09.2012: 
    
          try 
          { 
           SelfHost = new ServiceHost(typeof(T1), new Uri(HostUrlString)); 
    
           var smb = SelfHost.Description.Behaviors.Find<ServiceMetadataBehavior>() ?? 
              new ServiceMetadataBehavior() { }; 
           smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; 
    
           SelfHost.Description.Behaviors.Add(smb); 
    
           var throttleBehavior = new ServiceThrottlingBehavior(); 
           SelfHost.Description.Behaviors.Add(throttleBehavior); 
    
           var mexUrlString = String.Format(@"net.tcp://{0}:{1}{2}/mex", hostName, port, BaseUrlString); 
    
           // Add MEX endpoint 
           SelfHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), new Uri(mexUrlString)); 
    
           // Add binding 
           var binding = ConfigureBinding(); 
    
           // Add application endpoint 
           SelfHost.AddServiceEndpoint(typeof(T2), binding, ""); 
    
           if (ExtendedBinding) 
           { 
            foreach (ServiceEndpoint ep in SelfHost.Description.Endpoints) 
            { 
             foreach (OperationDescription op in ep.Contract.Operations) 
             { 
              var dataContractBehavior = op.Behaviors[typeof(DataContractSerializerOperationBehavior)] as DataContractSerializerOperationBehavior; 
    
              if (dataContractBehavior != null) 
              { 
               dataContractBehavior.MaxItemsInObjectGraph = Max; 
              } 
             } 
            } 
           } 
    
           // Open the service host to accept incoming calls 
           SelfHost.Open(); 
          } 
          catch (CommunicationException) 
          { 
           // log 
           SelfHost.Abort(); 
           return false; 
          } 
          catch (Exception) 
          { 
           // log 
           SelfHost.Abort(); 
           return false; 
          } 
    
         } 
         catch (Exception) 
         { 
          // log 
          return false; 
         } 
         return true; 
        } 
    
        private NetTcpBinding BaseConfigureBinding() 
        { 
         return new NetTcpBinding 
         { Security = { Mode = SecurityMode.None }, CloseTimeout = new TimeSpan(0, 0, 0, 5) }; 
        } 
    
        protected virtual NetTcpBinding ConfigureBinding() 
        { 
         var binding = BaseConfigureBinding(); 
    
         if (ExtendedBinding) 
         { 
          binding.MaxBufferPoolSize = Max; 
          binding.MaxReceivedMessageSize = Max; 
          binding.MaxBufferSize = Max; 
          binding.MaxConnections = 200; //rdoerig 12-03-2013 default value is 10: 
          binding.ListenBacklog = 200; //rdoerig 12-03-2013 default value is 10 : buffer of pending connections 
    
          binding.ReaderQuotas.MaxDepth = Max; 
          binding.ReaderQuotas.MaxStringContentLength = Max; 
          binding.ReaderQuotas.MaxArrayLength = Max; 
          binding.ReaderQuotas.MaxBytesPerRead = Max; 
          binding.ReaderQuotas.MaxNameTableCharCount = Max; 
    
          binding.CloseTimeout = new TimeSpan(0, 0, 10, 0); 
          binding.OpenTimeout = new TimeSpan(0, 0, 10, 0); 
          binding.ReceiveTimeout = new TimeSpan(0, 0, 10, 0); 
          binding.SendTimeout = new TimeSpan(0, 0, 10, 0); 
    
         } 
    
         return binding; 
        } 
    
        public bool StopService() 
        { 
         try 
         { 
          SelfHost?.Close(); 
         } 
         catch (Exception) 
         { 
          // log 
          return false; 
         } 
         return true; 
        } 
    } 
    

    ので、同じようこれをインスタンス化することができます。

     private readonly ServiceHosting<LoginService, ILoginService> _serviceHostLogin = new ServiceHosting<LoginService, ILoginService>(LoginUrl, true); 
    

    そして始めは/そのように停止:

      _serviceHostLogin.StartService(); 
          _serviceHostLogin.StopService(); 
    

    あなたを確認するために複数のサービスをホスティングするときにエラーが発生しない場合は、サービスのURIを異なるように設定する必要があります。

    new ServiceHosting<LoginService, ILoginService>("/Services/LoginService", true); 
    new ServiceHosting<ConfigService, IConfigService>("/Services/ConfigService", true); 
    
    +0

    これがどのようにOPの質問に対処しているか分かりません - ただ1つのサービスホストがあります –

    +0

    それは直接です。彼のコメントから、彼は同じアドレス+ポートに対して複数のServiceHostsをホストすることができないと彼は思った。私の例はそれが実際に可能であることを示しています。 –

    +0

    同じ物理アドレスとポートで2番目のサービスホストを開こうとするとエラーが表示されませんか?これがうまくいけば、私は非常に驚くだろう –

    -1

    あなたは、同じサービス・クラスで両方のインターフェースを実装し、一方のエンドポイントを持っていますが、個別の契約を結んでいることができます。

    [ServiceBehavior] 
    public partial class IntegratedService 
    { 
        // You can implement "base" methods here 
    } 
    

    次に、各インタフェースを実装しています

    public partial class IntegratedService : IFoo 
    { 
        // Implement IFoo interface 
    } 
    
    public partial class IntegratedService : IBar 
    { 
        // Implement IBar interface 
    } 
    

    はそれがお役に立てば幸いです。

    +0

    これは私の質問に述べられているように、私が望まないものです。あなたの例では、基本的にクラスを分割していますが、結局はそれがただ一つのクラスです。私は、それぞれのサービスに対して注入する必要のある依存性が異なるため、異なるタイプを持つ必要があります。 – artganify

    +0

    @artganifyエンドポイントあたり1つのサービスしか許可されていませんが、IIS内で同じdnsと同じポートを持つ2つの異なるサイトを持つようなものはありません。私はちょうどあなたが探している場合は申し訳ありませんが、いくつかのコードを同時に開始するように、あなたが望むように両方のサービスのコントロールを提供することができる "ベース"クラスで実装を提案した。 –

    +0

    @artganify私はRicardoPontualに同意する必要があります。要件を前提に、WCFが提供する唯一のサポートされているルートは、単一の実装を共有することです。あなたはこれらのサービスが完全に理念的に分かれていると言っていますが、一緒に開いたり閉じたりする必要があるなど、人為的な制約を課しています。ホスティングの仕組みにかかわらず、これらは別々のサービスであり、あなたはそれらを別々にホストして、周辺の要件を別の懸念事項として扱うことができます。 –