2011-07-20 3 views
1

J'ai une opération WCF MyGetVersion() qui renvoie une System.Version. Lors du débogage d'un appel à partir d'une référence de service Silverlight, j'ai vérifié que le service renvoie l'objet System.Version correct. Dans le service de référence, la méthode générée automatiquement:Silverlight ServiceReference provoque MethodAccessException

 public System.Version EndMyGetVersion(System.IAsyncResult result) { 
      object[] _args = new object[0]; 
      System.Version _result = ((System.Version)(base.EndInvoke("MyGetVersion", _args, result))); 
      return _result; 
     } 

soulève l'exception:

tentative par la méthode « DynamicClass.ReadVersionFromXml (System.Runtime.Serialization.XmlReaderDelegator, System.Runtime.Serialization.XmlObjectSerializerReadContext, System.Xml.XmlDictionaryString [], System.Xml.XmlDictionaryString []) 'pour accéder à la méthode' System.Version..ctor() 'a échoué.

J'ai dû activer l'assistant "break on CLR exception" pour le voir. Sinon, il s'agit d'une exception TargetInvocationException. Le constructeur System.Version() est public autant que je peux dire. Qu'est-ce que je fais mal?

Répondre

1

Le problème est que le constructeur de System.Version est public dans le .NET Framework, mais pas dans Silverlight (c'est interne, selon Reflector). Donc, alors que le type est sérialisable dans le framework complet, ce n'est pas dans Silverlight, et l'outil Add Service Reference devrait l'avoir remplacé par un type équivalent dans SL - c'est un bug dans l'outil (je vais le signaler à l'équipe produit , merci de le trouver).

Comme solutions de contournement, je vous suggère d'utiliser un type « de substitution » pour la version et l'utiliser dans votre contrat de service pour le transfert de données uniquement:

[DataContract] 
public class VersionDTO 
{ 
    [DataMember] 
    public int Major { get; set; } 
    [DataMember] 
    public int Minor { get; set; } 
    [DataMember] 
    public int Build { get; set; } 
    [DataMember] 
    public int Revision { get; set; } 

    public VersionDTO(Version version) { 
     this.Major = version.Major; 
     this.Minor = version.Minor; 
     this.Build = version.Build; 
     this.Revision = version.Revision; 
    } 
} 

[ServiceContract] 
public interface ITest 
{ 
    [OperationContract] 
    VersionDTO GetVersion(); 
} 

Une autre option, compte tenu de la question que vous avez mentionné dans la comment, remplacer la référence à la classe Version dans le proxy généré pour Silverlight par une classe qui lui est équivalente. La classe ci-dessous peut être utilisée pour désérialiser un objet Version dans SL depuis .NET.

[DataContract(Name = "Version", Namespace = "http://schemas.datacontract.org/2004/07/System")] 
    public class SLVersion 
    { 
     [DataMember(Order = 1, Name = "_Build")] 
     public int Build { get; set; } 
     [DataMember(Order = 2, Name = "_Major")] 
     public int Major { get; set; } 
     [DataMember(Order = 3, Name = "_Minor")] 
     public int Minor { get; set; } 
     [DataMember(Order = 4, Name = "_Revision")] 
     public int Revision { get; set; } 
    } 
+0

Merci, malheureusement le contrat est utilisé par d'autres services et d'autres clients s'attendent à une System.Version. Je devrais ajouter une autre opération qui le renvoie simplement comme une chaîne pour le client Silverlight je suppose. – GWTF

+0

Vous pouvez également modifier le proxy généré pour SL comme je l'ai ajouté dans la réponse ci-dessus. Le seul problème avec cette approche est que chaque fois que vous mettez à jour la référence de service de Silverlight, vous devrez remplacer la classe à nouveau. – carlosfigueira

Questions connexes