2009-04-17 7 views
0

J'essaie d'obtenir un objet d'une autre application en utilisant WCF. Avec les classes intégrées, cela fonctionne bien, mais je rencontre des problèmes lorsque je tente de renvoyer un type d'interface personnalisé à partir de l'opération WCF. Si j'inclue l'interface dans les deux applications séparément, ou si je l'indique comme un assembly partagé, j'obtiens le même résultat: une CommunicationException avec le message "Il y avait une erreur de lecture du pipe: Erreur non reconnue 109".Problème d'exposition des types d'interface complexes personnalisés dans les services WCF

L'interface ressemble à ceci:

[ServiceContract] 
public interface IBase { 
    int IntTest { 
     [OperationContract] 
     get; 
    } 
    String StringTest { 
     [OperationContract] 
     get; 
    } 
    IOther OtherTest { 
     [OperationContract] 
     get; 
    } 
} 

[ServiceContract] 
public interface IOther { 
    String StringTest { 
     [OperationContract] 
     get; 
    } 
} 

Mon serveur ressemble à ceci:

public partial class MainWindow : Window { 
    private Base fb; 
    private ServiceHost host; 

    public MainWindow() { 
     InitializeComponent(); 
     fb = new Base(); 
     host = new ServiceHost(fb, new Uri[] { new Uri("net.pipe://localhost") }); 
     host.AddServiceEndpoint(typeof(IBase), new NetNamedPipeBinding(), 
      "PipeReverse"); 
     host.Open(); 
    } 

    private void Window_Closing(object sender, CancelEventArgs e) { 
     host.Close(); 
    } 
} 

Et voici mon implémentation de l'interface:

[Serializable] 
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] 
public class Base : MarshalByRefObject, IBase { 
    public int IntTest { 
     get { return 4; } 
    } 

    public string StringTest { 
     get { return "A string from Base"; } 
    } 

    public IOther OtherTest { 
     get { return new Other(); } 
    } 
} 

[Serializable] 
[DataContract] 
public class Other : MarshalByRefObject, IOther { 
    [DataMember] 
    public string StringTest { 
     get { return "A string from Other"; } 
    } 

} 

Le client ressemble ceci:

public partial class Form1 : Form { 

    IBase obj; 

    public Form1() { 
     InitializeComponent(); 
     ChannelFactory<IBase> pipeFactory = new ChannelFactory<IBase>(
      new NetNamedPipeBinding(), new EndpointAddress(
      "net.pipe://localhost/PipeReverse")); 

     obj = pipeFactory.CreateChannel(); 
    } 


    private void button2_Click(object sender, EventArgs e) { 

     Console.WriteLine("Returns: " + obj.StringTest + " " + 
      obj.StringTest.Length); 
     Console.WriteLine("Returns: " + obj.IntTest); 
     Console.WriteLine(obj.OtherTest); 

    } 
} 

Tout fonctionne comme un charme, sauf cette ligne:

Console.WriteLine(obj.OtherTest); 

Il me donne un CommunicationException avec le message « Il y avait une erreur de lecture de la conduite: 109 Erreur non reconnue ». Autant que je sache, c'est un tuyau cassé en raison d'un état défectueux, mais je n'arrive pas à comprendre pourquoi, ou, plus important encore, comment le réparer. Des idées?

Je n'ai aucun fichier de configuration car tout est fait dans le code ci-dessus donc je ne sais pas comment activer le traçage, sinon je l'aurais inclus aussi.

+0

J'ai exécuté ce code sur ma machine. Bien qu'il n'y ait pas d'erreur retournée pour les méthodes IntTest et StringTest, il n'y a pas non plus de données. Quelque chose d'autre pourrait être faux. –

Répondre

2

La propriété retournée OtherTest doit être un type concret et non une interface, sinon la sérialisation ne fonctionnera pas.

+0

C'est tout! Merci. En effet, cela signifie que je devrai avoir les objets métier dans un assembly partagé. J'espérais pouvoir dupliquer l'interface mais je suppose que ça va devoir faire. Merci encore d'avoir aidé. – Farawin

0

Il s'agit généralement d'une erreur de sérialisation. Regardez l'attribut [KnownType]. Le moyen le plus simple de tester cela est d'appeler directement le DataContractSerializer. Vous pouvez utiliser ses méthodes WriteObject et ReadObject pour obtenir les vraies erreurs de sérialisation. Vous pouvez également inspecter le flux (FileStream généralement) pour vous assurer que vous tapez correctement les sérialisations.

Questions connexes