2010-11-06 19 views
7

Sto provando a giocare con WCF e penso di aver colpito un blocco. Il mio problema è che sono in grado di chiamare Add(double,double) e getPerson() dal "Client". Tuttavia, non sono in grado di chiamare alcun metodo dell'oggetto Person. Ho ridotto le classi con metodi semplici. Qui sono i miei frammenti di codice, per favore fatemelo sapere che cosa sto facendo male ..WCF restituire gli oggetti al client

Server Code

namespace Test.WebSvc{ 
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Sample")] 
    public interface ICalculator 
    { 
    [OperationContract] 
    double Add(double n1, double n2); 
    [OperationContract] 
    Person getPerson(); 
    } 


public class CalculatorService : ICalculator 
{ 
    public double Add(double n1, double n2) { return n1+n2 ; } 
    public Person getPerson(){ 
    Person tempPerson = new Person(); 
    return tempPerson; 
    } 
} 

[DataContract] 
public class Person{ 
[OperationContractAttribute] 
public string toString(){ 
return "This is a Person Object"; 
} 

Client Code

ServiceRef1.CalculatorClient client = ServiceRef1.CalculatorClient();//works 
Console.WriteLine(client.Add(1.0,2.0)); //this too works 
ServiceRef1.Person p = client.getPerson(); // this is OK., but is not doing what I wanted it to do 
Console.WriteLine(p.toString()); // I do not get "This is Person Object" 

Sono indovinando qualcosa di sbagliato con la mia classe Person dichiarazione .. ma non capisco cosa dovrei fare o cosa mi manca ..

Grazie!

risposta

8

Stai mescolando due concetti con il tuo tipo Person - quello che stai facendo non funzionerà.

Hai inserito un attributo DataContract sul tipo Person. Questo è corretto, perché hai un servizio che sta restituendo un Person. L'oggetto Person verrà serializzato e restituito al client di servizio (CalculatorClient in questo caso).

È necessario definire Person come questo:

[DataContract] 
public class Person 
{ 
    [DataMember] 
    public string Description { get; set; } 
} 

E nel vostro servizio calcolatrice:

public Person getPerson() 
{ 
    Person tempPerson = new Person(); 
    tempPerson.Description = "This is a Person Object"; 
    return tempPerson; 
} 

Questo perché lavoro la vostra Person oggetto è quello di tenere i dati, e portarlo dal server al client . Non è compito di definire metodi/operazioni, che dovrebbero invece essere eseguiti nelle classi di servizio (ad es. CalculatorService). L'aggiunta dell'attributo OperationContract non trasforma magicamente l'oggetto di trasferimento dati in un servizio.

+0

Ci è voluto un minuto per capire che DataContract non fa parte dello spazio dei nomi di ServiceModel. Si trova in System.Runtime.Serialization e sarà necessario aggiungere un riferimento nel progetto ad esso – Knightsy

10

Sì, hai raggiunto una barriera: WCF è un sistema basato su messaggi che scambia solo i dati serializzati , come XML o JSON, in formato testo o binario. Lo fa non ma passa attorno agli oggetti .NET "completi" con le loro piene capacità come i metodi e tutto ciò (come dovrebbe? È progettato per essere interoperabile , e non vedo come un client Ruby o PHP possa chiamare un metodo su un oggetto .NET).

WCF non è progettato per consentire l'accesso remoto agli oggetti, ma solo i messaggi tra client e server. Pertanto, tutto ciò che è possibile esprimere nello schema XML (tipi atomici, qualsiasi cosa come l'ereditarietà e la composizione) può essere serializzato e inviato tra le due parti.

Tutto ciò che non può essere modellato nello schema XML - come generici, interfacce, metodi/codice - non può essere passato tra client e server.

Ci sono modi e trucchi per aggirare questo se si controllano entrambe le estremità della comunicazione ed entrambi sono basati su .NET. In sostanza, dovresti mettere il tuo contratto di servizio e tutti i tuoi contratti dati (tutte le tue classi) in un assembly separato, che poi fai riferimento sia dal server (implementando il contratto di servizio), sia dal client che chiama il contratto.È possibile dire a WCF di riutilizzare i tipi già esistenti negli assiemi di riferimento, e in questo caso il client riutilizzerà la classe Person già pronta (con tutta la sua bontà .NET) dall'assembly condiviso comune invece di riutilizzare creazione di un proxy di dati lato client. Con questo trucco, è possibile fare in modo che WCF invii messaggi serializzati sul filo, ma sul lato client, stai ricreando un oggetto .NET completo con tutti i suoi metodi e tutto il resto.

Ancora: questo funziona benissimo se si controllano entrambe le estremità della comunicazione e entrambe le estremità utilizzano .NET. Qualsiasi interoperabilità è fuori dalla finestra con questo approccio.

+0

+1 Spiegazione dei dati serializzati –

Problemi correlati