Question

L'exécution d'un ServiceHost avec un seul contrat fonctionne comme suit:

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

J'aimerais maintenant ajouter un deuxième contrat (3ème, 4ème, ...). Ma première hypothèse serait d’ajouter simplement des points de terminaison comme celui-ci:

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

Mais bien sûr, cela ne fonctionne pas, car lors de la création de ServiceHost, je peux passer soit MyService1 en tant que paramètre, soit MyService2. seul peut fournir une implémentation?
J'ai l'impression que je manque le point, ici. Bien sûr, il doit y avoir un moyen de fournir une implémentation pour chaque contrat final que j'ajoute, ou pas?

Était-ce utile?

La solution

Vous devez implémenter les deux services (interfaces) dans la même classe.

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

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

    #region IMyService2
    #endregion
}

Pour info: j’utilise fréquemment des classes partielles pour faciliter la lecture du code de ma classe d’hôte:

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

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

Autres conseils

Je suis actuellement confronté au même problème et j'ai décidé de procéder à la mise en œuvre ci-dessous. Je ne suis pas sûr que le nombre de contrats de service pose un problème de performances, mais lors de ma dernière mise en œuvre, j'aurai probablement entre 10 et 15 contrats de service, soit environ 10 à 15 hôtes de service.

J'héberge tous mes services WCF dans un seul service 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);
    }

}

N'hésitez pas à commenter ce type de configuration et tout problème éventuel, en particulier en ce qui concerne les performances.

Cette réponse est une réponse supplémentaire au commentaire de la réponse acceptée par chilltemp.

Sam, vous devriez vraiment déterminer pourquoi vous avez besoin de contrats 10-50 et essayer de trouver une autre solution. J'ai examiné les normes de codage WCF de Juval Lowy (disponibles sur http://www.idesign.net/ ) et j'ai trouvé les références suivantes:

  

3 Contrats de service   ...   4. Évitez les contrats avec un membre.   5. S'efforcer d'avoir trois à cinq membres par contrat de service.   6. Ne pas avoir plus de vingt membres par contrat de service. Douze est probablement la limite pratique.

Il ne mentionne pas de limite quant au nombre de contrats exécutés (que je puisse trouver), mais je ne peux pas l’imaginer en train de considérer 50 contrats d’un service comme une pratique exemplaire. Une solution qui fonctionne bien consiste à utiliser le partage de membres pour des fonctions similaires.

Par exemple, si vous utilisez le service WCF pour effectuer des calculs sur 2 valeurs, vous pouvez avoir 4 membres du côté service: Ajouter (x, y), Soustraire (x, y), Multiplier (x, y), Diviser (x, y). Si vous les combinez en un membre plus générique et utilisez un objet pour transmettre les données nécessaires, vous pouvez facilement réduire le nombre de membres et augmenter l'évolutivité. Exemple: PeformCalculation (obj) où obj a les propriétés x, y et action (addition, soustraction, multiplication, division).

J'espère que cela vous aidera.

J'ai trouvé une autre solution à ce problème en utilisant le RoutingService . Chaque contrat doit toujours être hébergé dans son propre ServiceHost , mais il peut y avoir un RoutingService au-dessus de tous - et les présenter sur un "noeud final" unifié. J'ai également écrit un article de codeproject à ce sujet. L'exemple de code est également disponible sur Bitbucket .

La réponse de

chili fonctionnera si vous êtes d'accord avec les contrats partagés par le service. Si vous souhaitez les séparer, essayez ceci:

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
}

Modifier: comme Matt l'a signalé, plusieurs points d'extrémité seraient nécessaires pour chaque service / contrat

Personne enpoint documenté. Si vous en utilisez plusieurs (en tant que groupe, à partir d'une URL commune, par exemple http), vous devez utiliser la même instance de liaison (pas plus), c'est-à-dire.

Votre échantillon:

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

devrait être un seul nouveau Binding (), j'ai testé sur 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();

Je suis tout à fait d'accord avec la classe partielle implémentant peu de contrats dans quelques fichiers.

Pourquoi ne pas le scinder avec une adresse de base et plusieurs services / contrats en dessous? Je ne suis pas derrière une machine de développement en ce moment, mais quelque chose comme:

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

Chaque service implémentant son propre ServiceContract.

Vous pouvez changer
Classe publique WcfEntryPoint: IMyService1, IMyService2
à
classe partielle publique WcfEntryPoint: IMyService1
classe partielle publique WcfEntryPoint: IMyService2

Exemple

Ai-je oublié quelque chose ou la solution la plus simple n'est-elle pas mentionnée ici? La solution la plus simple est la suivante: n’utilisez pas plusieurs interfaces pour le service Web.

Mais cela ne signifie pas que vous pouvez toujours séparer vos interfaces. C'est pourquoi nous avons l'héritage d'interface.

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

La méta-interface hérite de toutes les autres interfaces.

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

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

Ensuite, le service n'a plus qu'une interface méta.

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

   public void DoSomethingElse()
   {
       // code here
   }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top