it-swarm.com.de

Führen Sie WCF ServiceHost mit mehreren Verträgen aus

Das Ausführen eines ServiceHost mit einem einzigen Vertrag funktioniert folgendermaßen:

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

Nun möchte ich einen zweiten (dritten, vierten, ...) Vertrag hinzufügen. Meine erste Vermutung wäre, einfach weitere Endpunkte wie diese hinzuzufügen:

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

Aber das funktioniert natürlich nicht, da ich bei der Erstellung von ServiceHost entweder MyService1 als Parameter oder MyService2 übergeben kann - also kann ich meinem Service viele Endpunkte hinzufügen, aber alle müssen den gleichen Vertrag verwenden, da ich nur angeben kann eine Implementierung?
Ich hatte das Gefühl, dass ich hier den Punkt verpasse. Sicher muss es eine Möglichkeit geben, eine Implementierung für jeden Endpunktvertrag bereitzustellen, den ich hinzufüge, oder nicht?

51
Sam

Sie müssen beide Dienste (Schnittstellen) in derselben Klasse implementieren.

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

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

    #region IMyService2
    #endregion
}

Zu Ihrer Information: Ich verwende häufig Teilklassen, um den Code meiner Host-Klasse leichter lesbar zu machen:

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

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

Ich bin derzeit mit dem gleichen Problem konfrontiert und habe mich für die unten stehende Implementierung entschieden. Ich bin mir nicht sicher, ob bei so vielen Serviceverträgen Leistungsprobleme auftreten, aber in meiner endgültigen Implementierung werde ich wahrscheinlich etwa 10 - 15 Serviceverträge haben, also etwa 10-15 ServiceHosts.

Ich hoste alle meine WCF-Dienste in einem einzigen Windows-Dienst.

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

}

Fühlen Sie sich frei, diese Art von Einrichtung zu kommentieren, und wenn es Probleme gibt, insbesondere in Bezug auf die Leistung.

17
Saajid Ismail

Diese Antwort ist eine weitere Antwort auf den Kommentar in der akzeptierten Antwort von chilltemp.

Sam, Sie sollten wirklich herausfinden, warum Sie 10-50-Verträge benötigen, und versuchen, eine andere Lösung zu finden. Ich habe die WCF-Codierungsstandards von Juval Lowy (auf http://www.idesign.net/ ) durchgesehen und die folgenden Referenzen gefunden: 

3 Serviceverträge ... 4. Vermeiden Sie Verträge mit einem Mitglied . 5. Bemühen Sie sich, drei bis fünf Mitglieder pro Servicevertrag zu haben. 6. Sie haben nicht mehr als zwanzig Mitglieder pro Servicevertrag. Zwölf ist wahrscheinlich die praktische Grenze.

Er erwähnt kein Limit für Vertragsimplementierungen (was ich finden kann), aber ich kann mir nicht vorstellen, dass er 50 Verträge für einen Service als eine Best Practice betrachtet. Eine Lösung, die ich gefunden habe, ist die Verwendung der Mitgliederfreigabe für ähnliche Funktionen.

Wenn Sie beispielsweise den WCF-Dienst verwenden, um Mathematik für 2 Werte auszuführen, haben Sie möglicherweise 4 Mitglieder auf der Serviceseite: Add (x, y), Subtrahieren (x, y), Multiplizieren (x, y), Dividieren (x) , y). Wenn Sie diese zu einem generischeren Element zusammenfassen und ein Objekt verwenden, um die erforderlichen Daten zu übergeben, können Sie die Mitgliederanzahl leicht reduzieren und die Skalierbarkeit erhöhen. Beispiel: PeformCalculation (obj) wobei obj die Eigenschaften x, y und action (addieren, subtrahieren, multiplizieren, dividieren) hat.

Hoffe das hilft.

10
Chris Porter

Ich habe eine andere Lösung für dieses Problem gefunden, indem ich die Klasse RoutingService verwendet. Jeder Vertrag muss immer noch in seiner eigenen ServiceHost gehostet werden, es kann jedoch auch eine RoutingService vorhanden sein, die sich über allen befindet - und sie über einen einheitlichen "Endpunkt" präsentiert. Ich habe auch einen Codeprojekt-Artikel darüber geschrieben. Der Beispielcode ist auch unter Bitbucket verfügbar.

8
m0sa

die Antwort von chili funktioniert, wenn Sie mit den Verträgen, die der Dienst teilt, zufrieden sind. Wenn Sie möchten, dass sie getrennt werden, versuchen Sie Folgendes:

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
}

Bearbeiten: Wie Matt gepostet hat, wären für jeden Service/Vertrag mehrere Endpunkte erforderlich

6
Chris Porter

Niemand hat Belege dokumentiert. Wenn mehr als eine verwendet wurde (als Gruppe, aus der üblichen URL, z. B. http), muss dieselbe Bindungsinstanz (nicht mehr) verwendet werden, d.

Ihre Probe:

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

sollte nur ein neues Binding () sein, habe ich über http getestet.

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

Ich stimme vollkommen zu, dass die Teilklasse einige Verträge in wenigen Dateien umsetzt.

2
Jacek Cz

Wie wäre es, wenn Sie es mit einer Basisadresse und mehreren Services/Verträgen darunter aufteilen?

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

Jeder Service implementiert einen eigenen ServiceContract.

Du kannst ändern
public class WcfEntryPoint : IMyService1, IMyService2
zu
public partial class WcfEntryPoint : IMyService1
public partial class WcfEntryPoint : IMyService2

Beispiel

1

Habe ich etwas verpasst oder wird die einfachste Lösung hier nicht erwähnt? Die einfachste Lösung ist folgende: Verwenden Sie nicht mehrere Schnittstellen für den Webdienst.

Das bedeutet jedoch nicht, dass Sie Ihre Schnittstellen trotzdem trennen können. Deshalb haben wir Interface-Vererbung.

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

Die Meta-Schnittstelle erbt von allen anderen Schnittstellen.

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

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

Dann hat der Dienst nur die Meta-Schnittstelle.

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

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