8
votes

WCF: interfaces, génériques et service de service

J'ai ce qui suit: xxx pré>

Lorsque j'exécute la méthode d'obtention, je reçois l'erreur suivante: p>

Il y a eu une erreur lors de la tâche de Serialize paramètre http://tempuri.org/:GETRESULT . Le message InNeReException était "Type 'pps.core.domainmodel.support.action.acteResult" [[PPS.Core.DomainModel.sportProgram.Sapprogram, PPS.Core.DomainModel, version = 1.0.0.0, Culture = neutre, PublickeyToken = NULL]] 'AVEC LE NOM DE CONTRAT DE DONNÉES' ActionResultOnyType: http: // schemas.datacontract.org/2004/07/pps.core.domainmodel.support.action 'n'est pas attendu. Ajoutez tous les types non connus de manière statique à la liste des types connus - par exemple, à l'aide de l'attribut connu deTypeAttribute ou en les ajoutant à la liste des types connus passés à DatacontractSérialiseur. '. S'il vous plaît voir Infantaxception pour plus de détails. P> BlockQuote>

de cette erreur, je peux voir que cela peut résoudre l'actionResult, mais il ne peut pas résoudre ISPORTROGRAM, même si j'ai ServiceknownType (typeof (ActionResult )) strong> sur mon interface de service ... p>

Remarque Il s'agit du talon de référence généré ressemble à ceci. Je peux donc voir que les types connus sont mis à l'arrière correctement: P>

public interface IActionResult<T> 
{
    T Result { get; set; } 
}


1 commentaires

Le type actionResult que Serializer s'attend à être différent du type ActionResult fourni dans ServiceknownType !


5 Réponses :


0
votes

Spécifiez-vous des interfaces dans les objets et non types de béton?

PPS.Core.DomainModel.Support.Action.ActionListResult<IList<PPS.Core.DomainModel.SportProgram.ISportProgram>>


0 commentaires

0
votes

Vous retournez un IList de T. C'est peut-être que le système a des problèmes de découverte de ce que T est.

Je ne sais pas si c'est correct pour renvoyer une interface plutôt qu'un type.


0 commentaires

15
votes

Eh bien, je pense que c'est un autre cas de la SOA vs. OOP "Mismatch d'impédance". Les deux monde sont assez séparés.

Dans WCF, tout ce qui est passé du client au serveur est passé sous la forme de messages sérialisés - Aucune références n'est utilisée.

Cela signifie: tout ce que vous voulez sérialiser sur le client, envoyez-le sur le serveur, et de les désérialiser et l'utiliser là-bas, doit être concret , vous ne pouvez pas passer des interfaces, vous ne pouvez pas utiliser Generics "non résolus" - vous devez l'épeler. Fondamentalement, tout ce qui est passé du client sur le fil au serveur doit être expressible dans le schéma XML.

Cela a beaucoup d'implications:

  • Aucune interface - Vous ne pouvez pas transmettre des interfaces - vous devez travailler avec des types de béton
  • Non "Automatique" Héritage - Vous ne pouvez pas simplement définir une classe de base et transmettre des cours dérivés en fonction de celle-ci - celles-ci doivent également être spécifiées (c'est ce que l'attribut ServiceknownType est pour)
  • Aucun générique automatique - à nouveau, vous devez utiliser des types de béton

    Cela peut sembler comme beaucoup de restrictions - mais c'est parce que WCF utilise toute la communication basée sur des messages - il ne peut pas gérer les références, l'héritage, les génériques, etc. - vous devez l'épeler.

    Donc, je n'ai pas vraiment de réponse pour vous en soi, je pense simplement que vous devez repenser votre stratégie et modifier la façon dont votre client et votre serveur échangent des informations sur WCF.

    marc

    PS: J'ai fait plus de recherches et contrairement à toute ma compréhension, il semble y avoir un moyen de sérialiser tout ce qui est basé sur une interface et / ou une classe de base abstraite sur le fil, à condition que vous puissiez être sûr que ce soit Toujours seulement .net sur l'une ou l'autre extrémité du fil (c'est-à-dire qu'il est pas interopérable avec par exemple Java).

    Voir Publication de blog Aaron Skonnard sur NetDataContractSerializer et une autre Publication du blog et Encore un autre montrer comment utiliser NetDatacontractSerializer pour pouvoir être capable passer autour des choses comme iPerson comme paramètres sur vos méthodes.


2 commentaires

Je suis prêt à donner à WCF toutes les astuces dont il a besoin, mais je ne peux pas éviter d'utiliser les interfaces ou les génériques ... Si d'une manière ou d'une autre, je peux vous débarrasser des interfaces puis-je toujours utiliser des génériques ?? L'inverse est également vrai si je peux me débarrasser des génériques puis-je toujours utiliser des interfaces ... ce qui signifie que c'est juste le combinat de la 2 qui me causent des problèmes ?? Parce que je pouvais créer une version plus spécifique d'IactionResult qui ne nécessite pas les génériques à utiliser ...


Mise à jour de mon message avec de nouvelles informations que j'ai trouvées lors de la recherche de cette question - espérons que cela vous aidera!



2
votes

C'est l'un des problèmes que je résous avec Servicestack.net - My Open Source .NET et Mono Web Web Cadre de services.

La pile de services a été fortement influencée par Modèle d'objet de transfert de données Martin Fowlers car il vous permet de simplement Utilisez DTO pour définir vos services Web - c'est-à-dire la solution SOA :).

J'évite cette limitation inhérente à la WCF en générant mes propres WSDL qui se comportent comme vous l'attendez. En tant qu'envirant à remplacer le modèle de configuration complexe / servicecontraitrage de WCF - les services Web SOAP fonctionnent également sur mono - Voir la démo en direct .


1 commentaires

Semble intéressant mais le lien de démonstration en direct est un 404



1
votes

C'est une question ancienne et même si la réponse acceptée est totalement correcte, je m'engageai dans la recherche d'un problème de similiaire et je pensais pouvoir partager mes expériences. C'est souvent un mal de tête, mais il est possible d'utiliser des génériques combinés à des interfaces avec WCF. Voici un exemple de travail d'une autre implémentation (SIMILIAR) que j'ai faite:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(ActionResult<ISportProgram>))] // Actual implementation of container, but interface of generic.
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

[KnownType(typeof(SportProgram))] // Actual implementation here.
public class ActionResult<T>
{
    // Other stuff here
    T FooModel { get; set; }
}


0 commentaires