53 votes

Exécuter un ServiceHost WCF avec plusieurs contrats

L'exécution d'un ServiceHost avec un seul contrat fonctionne bien comme ça :

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 (troisième, quatrième, ...) contrat. Ma première idée serait d'ajouter d'autres points d'extrémité comme ceci :

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, puisque lors de la création du ServiceHost, je peux passer soit MyService1 comme paramètre, soit MyService2. Je peux donc ajouter beaucoup de points de terminaison à mon service, mais tous doivent utiliser le même contrat, puisque je ne peux fournir qu'une seule implémentation ?
J'ai l'impression de passer à côté de l'essentiel, ici. Il doit bien y avoir un moyen de fournir une implémentation pour chaque contrat d'extrémité que j'ajoute, ou pas ?

63voto

chilltemp Points 3777

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 rendre le code de ma classe hôte plus facile à lire :

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

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

12 votes

Zut. J'ai besoin de plus que 2 contrats de service, je pense 10-50, et pour ce nombre cette approche est un peu lourde - ce n'est pas très utile d'avoir tous ces points d'entrée dans une seule classe :( Il n'y a pas d'autre moyen ?

0 votes

Ma solution vous permettrait de répartir les contrats en différentes classes. Vous pourriez également combiner ma solution avec celle de Chill pour avoir disons 5 classes, chacune avec 2 points finaux. Je suis cependant très curieux de savoir pourquoi vous avez besoin de 50 contrats. Vous devriez consulter les meilleures pratiques de Juval à l'adresse suivante idesign.net .

1 votes

Je suis d'accord avec le commentaire de Chris. Il semble que vous deviez simplifier votre conception.

17voto

Saajid Ismail Points 1950

Je suis actuellement confronté au même problème, et j'ai décidé d'opter pour l'implémentation ci-dessous. Je ne sais pas si le fait d'avoir autant de contrats de service pose des problèmes de performance, mais dans mon implémentation finale, j'aurai probablement 10 à 15 contrats de service, et donc 10 à 15 ServiceHosts.

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 à nous faire part de vos commentaires sur ce type d'installation, et si vous rencontrez des problèmes, notamment en matière de performances.

0 votes

C'est compliqué

1 votes

Ce serait encore mieux si vous utilisiez un conteneur d'injection de dépendances pour résoudre les implémentations =)

0 votes

Meilleure solution permettant d'isoler les services et de les attribuer individuellement,

10voto

Chris Porter Points 2394

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

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

3 Contrats de service ... 4. Éviter les contrats avec un seul 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 sur les implémentations de contrats (que je puisse trouver) mais je ne peux pas imaginer qu'il considère 50 contrats sur un service comme quelque chose qui ressemble à une meilleure pratique. Une solution que j'ai trouvée et qui fonctionne bien est d'utiliser le partage de membres pour des fonctions similaires.

Par exemple, si vous utilisez le service WCF pour effectuer des mathématiques sur 2 valeurs, vous pouvez avoir 4 membres du côté du service : Add(x,y), Subtract(x,y), Multiply(x,y), Divide(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 (ajouter, soustraire, multiplier, diviser).

J'espère que cela vous aidera.

0 votes

Juval parle de 3-5 membres sur un contrat. Je parle de 10-50 contrats pour un service (chaque contrat contenant 3-5 membres). C'est peut-être ce qui crée la confusion ?

2 votes

Ce n'est pas de la confusion, il ne mentionne pas de limite sur les contrats mais je ne voudrais pas m'engager dans la voie de 50 contrats sur un service. Il devrait y avoir une certaine forme de refactoring qui pourrait être faite sur vos contrats pour réduire la taille / le nombre d'entre eux. C'est votre application mais je chercherais d'autres options.

9voto

m0sa Points 5501

J'ai trouvé une autre solution pour ce problème en utilisant une méthode d'évaluation de l'impact sur l'environnement. RoutingService classe. Chaque contrat doit toujours être hébergé dans son propre fichier ServiceHost mais il peut y avoir un RoutingService qui se trouve au-dessus de tous les autres - et les présente sur un "point final" unifié. J'ai également écrit un article de codeprojet à ce sujet. Le code d'exemple est également disponible sur Bitbucket .

6voto

Chris Porter Points 2394

La réponse de chili fonctionnera si vous êtes d'accord pour que les contrats soient partagés par le service. Si vous voulez qu'ils soient séparés, 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
}

Edit : Comme Matt l'a indiqué, cela nécessiterait plusieurs points de terminaison pour chaque service/contrat.

0 votes

C'est parfait. C'est exactement ce que je cherchais quand j'ai commencé à lire ce fil. Au départ, je pensais que ce serait impossible à juger d'après l'essentiel de ce fil de discussion, mais cela fonctionne bien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X