2016-04-07 17 views
1

Ich habe zwei völlig separate Dienste (zusammen mit ihren Verträgen), die völlig unterschiedliche Abhängigkeiten sowie völlig unterschiedliche Verantwortlichkeiten haben. Aber Dinge, die sie gemeinsam bekam sind:Hosten mehrerer Dienste innerhalb eines Diensthosts?

  • Sie müssen geöffnet/geschlossen werden zusammen
  • Sie teilen die gleiche Basisadresse
  • Sie haben die gleiche Bindung/Transport

Dummy Verträge :

public class IFoo { 
    void Foo(); 
} 

public class IBar { 
    void Bar(); 
} 

Nun, was ich tun möchte, ist, sie beide in demselben Service-Host zu hosten. Ich bin mir bewusst, dass es möglich ist, beide Dienste als Endpunkte zu entlarven und sie in der gleichen Diensttyp wie folgt implementieren:

public class FooBar : IFoo, IBar { } 

var host = new ServiceHost(typeof(FooBar)); 

Jedoch habe ich nach einem Weg, bin auf der Suche, so etwas zu tun:

public class FooImpl : IFoo { } 

public class BarImpl : IBar { } 

var host = new ServiceHost(); 
host.AddEndpoint(typeof(FooImpl); 
host.AddEndpoint(typeof(BarImpl); 
host.Open(); 

So kann ich meine Service-Implementierungen nett und ordentlich halten, jeder mit seinen eigenen Abhängigkeiten anstelle eines god-Objekts für alles.

Jeder hat eine Idee, wie dies zu erreichen ist?

+0

Müssen Sie beide Dienste im selben ServiceHost hosten, oder akzeptieren Sie mehrere ServiceHost-Instanzen mit jeweils eigenen Diensten und Endpunkten? –

+0

@WicherVisser Leider nicht, weil alle Dienste auf dem gleichen Port laufen müssen. – artganify

+0

Mögliches Duplikat von [WCF ServiceHost mit mehreren Verträgen ausführen] (http://stackoverflow.com/questions/334472/run-wcf-servicehost-with-multiple-contracts) –

Antwort

4

Sie können mehrere ServiceHosts mit jeweils eigenem Service und Endpunkt hosten, die alle die gleiche Basisadresse und denselben Anschluss haben. Hier ist meine Implementierung ist, in eine ServiceHosting Klasse gekapselt:

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

Dies kann wie so instanziiert werden:

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

Und gestartet/gestoppt etwa so:

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

Um sicherzustellen, dass Sie Wird beim Hosten mehrerer Dienste kein Fehler angezeigt, sollten Sie die URIs für Dienste anders konfigurieren, z

+0

Nicht sicher, wie dies die OP-Frage adressiert - es gibt immer noch nur einen Service-Host –

+0

tut es nicht - direkt. Aus seinen Kommentaren habe ich verstanden, dass der OP dachte er könnte nicht mehrere ServiceHosts für die gleiche Adresse + Port hosten. Mein Beispiel zeigt, dass das tatsächlich möglich ist. –

+0

Erhalten Sie nicht nur einen Fehler, wenn Sie versuchen, den zweiten Service-Host unter derselben physischen Adresse und demselben Port zu öffnen? Ich würde sehr überrascht sein, wenn das funktioniert –

-1

Sie können beide Schnittstellen in derselben Serviceklasse implementieren und einen Endpunkt haben, aber mit getrennten Verträgen:

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

Dann wird jede Schnittstelle implementieren:

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

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

Hoffe, es hilft.

+0

Das ist genau das, was ich nicht will, wie in meiner Frage angegeben.In Ihrem Beispiel teilen Sie die Klassen im Grunde nur auf, aber am Ende ist es immer noch nur eine Klasse. Ich muss verschiedene Typen wegen der verschiedenen Abhängigkeiten haben, die ich für jeden Service injizieren muss. – artganify

+0

@artganify nur ein Service pro Endpunkt ist erlaubt, was Sie wollen, sind wie zwei verschiedene Websites mit gleichen DNS und den gleichen Port innerhalb von IIS haben, können Sie nicht. Ich habe nur diese Implementierung vorgeschlagen, weil Sie in der "Basis" -Klasse die Kontrolle für beide Dienste bereitstellen können, wie Sie wollen, wie zum Beispiel Code gleichzeitig zu starten, Entschuldigung, wenn Sie nicht suchen. –

+0

@artganify Ich würde RicardoPontual hierüber zustimmen müssen. Angesichts Ihrer Anforderungen ist die gemeinsame Nutzung einer einzigen Implementierung die einzige unterstützte Route, die WCF Ihnen anbietet. Sie stellen fest, dass diese Dienste vollständig ideologisch getrennt sind, und dennoch auferlegen Sie ihnen künstliche Zwänge, wie sie müssen offen/geschlossen zusammen sein. Unabhängig von Ihrem Hosting-Mechanismus sind dies separate Dienste und sollten als solche behandelt werden. Sie können sie separat hosten und dann Ihre peripheren Anforderungen als separate Probleme behandeln. –

Verwandte Themen