2009-04-21 6 views
2

J'ai un problème bizarre qui fait ma tête dansLe passage d'une classe dérivée à une méthode de service Web qui prend un type abstrait

je les classes suivantes définies dans un seul projet.

public abstract class AbstractUnitModel { 

     public void executeRemoteModel(){} 

} 

//this class also implements a seperate interface, but I dont think that is the issue 
public class BlastFurnaceUnitModel : AbstractUnitModel, IUnitModel {} 

maintenant, si je tente quelque chose comme ça, il fonctionne comme prévu:

class Class1 
{ 

    public void method1() { 

     BlastFurnaceUnitModel b = new BlastFurnaceUnitModel(); 
     method2(b); 
    } 

    public void method2(AbstractUnitModel a) {} 

} 

maintenant, j'ai un autre projet qui expose une méthode Web. Cette méthode prend un AbstractUnitModel et l'exécute à distance, puis renvoie les résultats au client. Donc, sur le serveur d'avoir ceci:

[WebMethod] 
public AbstractUnitModel remotelyExecuteUnitModel(UnitModelWrapperInterface.AbstractUnitModel unitModel) 
     { 

      unitModel.executeRemoteModel(); 
      return unitModel; 

     } 

Et sur le client je ceci:

public void remoteExecution() { 

       var unitModelWebService = new UnitModelRemoteServer.RemoteModelExecutionWebService(); 
       unitModelWebService.remotelyExecuteUnitModelCompleted += new UnitModelRemoteServer.remotelyExecuteUnitModelCompletedEventHandler(remoteExecutionCompleted); 
       unitModelWebService.remotelyExecuteUnitModelAsync(this.remoteBF); 
      } 

Mais mon projet ne compilera pas, et je reçois ces erreurs: Erreur 109 La meilleure surcharge match de méthode pour 'CalibrationClient.UnitModelRemoteServer.RemoteModelExecutionWebService.remotelyExecuteUnitModelAsync (CalibrationClient.UnitModelRemoteServer.AbstractUnitModel)' a des arguments invalides

Erreur 110 Argument « 1 »: ne peut pas convertir « UnitModelWrapperInterface.BlastFurnaceUnitModel » à « CalibrationClient.UnitModelRemoteServer.AbstractUnitModel »

Je ne peux pas comprendre pourquoi ce qui se passe. J'ai des références dans le projet de serveur à l'espace de noms où AbstractUnitModel est défini. La seule chose qui m'a l'air un peu drôle est qu'il utilise AbstractUnitModel de l'espace de noms 'CalibrationClient' plutôt que UnitModelWrapperInterface. Il semble que lorsque VS génère le proxy pour un webservice sur le client, il crée une implémentation abstraite partielle de AbstractUnitModel. Est-ce la source de mon problème? Si oui, comment pourrais-je y remédier?

edit pour la solution: Comme indiqué, le client doit connaître toutes les classes qui pourraient être envoyées à travers le fil. J'ai fini par résoudre ce problème en supprimant les classes proxy générées et en référençant la bibliothèque commune. Pas idéal mais assez bon dans cette situation.

+0

Re votre commentaire - J'ai manqué le fait que vous essayiez d'utiliser les objets serveur sur le client. Vous devez utiliser des objets proxy sur le client avec les services Web "old style". Avec XmlInclude, vous devriez obtenir une version proxy de BlastFurnaceUnitModel. –

Répondre

0

Vous pouvez essayer [XmlInclude]:

[XmlInclude(typeof(BlastFurnaceUnitModel))] 
public abstract class AbstractUnitModel {...} 

peine d'essayer, au moins ...

(modifier) ​​ou au niveau de la méthode:

[WebMethod(), XmlInclude(typeof(BlastFurnaceUnitModel))] 
public AbstractUnitModel remotelyExecuteUnitModel(...) {...} 

(moins sûr de la deuxième)

+0

Merci pour votre réponse rapide Marc, mais cela ne semble pas avoir d'impact sur mon problème. Je reçois les mêmes erreurs de compilation. – Alex

1

Cela se produit car l'outil WSDL crée des classes proxy (ouvrir le code de service fi le et vous les verrez) qui sont les classes utilisées pour instancier quand les objets viennent du service.

Si vous voulez éviter cela, il est préférable d'utiliser WCF. Cela concerne également les objets retournés polymorphes, car les services web ne peuvent pas gérer le polymorphisme (donc le type de retour de la méthode remotelyExecuteUnitModel est toujours AbstractUnitModel.)

+0

Ok, je suppose que c'est parce que le client n'a aucun moyen de déterminer la nature de la classe à laquelle il a été envoyé. L'utilisation de WCF n'est pas une option à ce stade. Y a-t-il un moyen de faire en sorte que les classes dérivées soient incluses dans les classes proxy (ce n'est pas élégant mais à ce stade j'ai besoin que les choses fonctionnent)? Ou est-ce que c'est ce que le code de Marc est censé faire? – Alex

+0

@Alex: Oui - l'ajout de XmlInclude est destiné à générer la sous-classe dans le code proxy (côté client). –

+0

Je me suis retrouvé à travailler en supprimant la définition de la classe proxy et en référençant ma bibliothèque commune dans le fichier reference.cs. – Alex

0

La classe exposée dans votre WebService est créée dans un espace de noms différent à l'intérieur de votre service. référence.

Je crée généralement une méthode comme

WebServiceReferenceNS.AbstractUnitModel ToWebServiceModel(AbstractUnitModel unitModel) 
{ 
} 

pour préparer les classes pour le WebService. Mais j'aimerais voir s'il y a une solution plus élégante.

Questions connexes