2010-11-06 31 views
7

Estoy tratando de jugar con WCF y creo que he tocado un bloque. Mi problema es que puedo llamar al Add(double,double) y getPerson() desde el "Cliente". Sin embargo, no puedo llamar a ningún método del objeto Person. He desmantelado las clases con métodos simples. Aquí están mis fragmentos de código, por favor, hágamelo saber lo que estoy haciendo mal ..WCF devolver objetos al cliente

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" 

que supongo que algo anda mal con mi declaración de la clase Persona .. pero no entiendo qué debo hacer o qué me falta ...

¡Gracias!

Respuesta

8

Está mezclando dos conceptos con su tipo Person - lo que está haciendo no funcionará.

Has puesto un atributo DataContract en el tipo Person. Esto es correcto, porque tiene un servicio que devuelve un Person. El objeto Person se serializará y se devolverá a su cliente de servicio (CalculatorClient en este caso).

Debe definir Person así:

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

Y en su servicio de calculadora:

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

Esto se debe a que el trabajo de su Person del objeto consiste en almacenar datos, y llevarla del servidor al cliente . No es su trabajo definir métodos/operaciones, que en su lugar deben hacerse en sus clases de servicio (por ejemplo, CalculatorService). Agregar el atributo OperationContract no convierte mágicamente el Objeto de Transferencia de Datos en un Servicio.

+0

Me tomó un minuto darme cuenta de que DataContract no es parte del espacio de nombres de ServiceModel. Está en System.Runtime.Serialization y también necesitarás agregar una referencia en tu proyecto a él – Knightsy

10

Sí, ha topado con una barrera - WCF es un sistema basado en mensajes que solo intercambia datos serializados, ya sea como XML o JSON, en formato de texto o binario. Lo hace no pase objetos ".NET" completos con todas sus capacidades como métodos y todo eso (¿cómo debería? Está diseñado para ser interoperable, y no veo cómo un cliente Ruby o PHP podría llamar a un método en un objeto .NET).

WCF no está diseñado para permitir el acceso remoto a objetos, simplemente pasa mensajes entre el cliente y el servidor. Por lo tanto, cualquier cosa que pueda expresar en un esquema XML (tipos atómicos, cualquier cosa como herencia y composición) puede ser serializada y enviada entre las dos partes.

Cualquier cosa que no se puede se puede modelar en esquema XML, como genéricos, interfaces, métodos/código, no se puede pasar entre el cliente y el servidor.

Existen formas y trucos para evitar esto si controla ambos extremos de la comunicación y ambos están basados ​​en .NET. Básicamente, tendría que poner su contrato de servicio y todos sus contratos de datos (todas sus clases) en un conjunto separado, que luego hace referencia tanto desde el servidor (implementando el contrato de servicio), como desde el cliente que llama al contrato.Puede indicarle a WCF que reutilice los tipos que ya existen en los ensamblados a los que hace referencia, y en este caso, el cliente reutilizará la clase listada Person (con todas sus bondades .NET) de su ensamblado común compartido en lugar de volver a usar creando un proxy de datos del lado del cliente. Con este truco, puede hacer que WCF envíe mensajes serializados a través del cable, pero en el lado del cliente, está recreando un objeto .NET completo con todos sus métodos y todo.

De nuevo: esto funciona muy bien siempre que controle ambos extremos de la comunicación, y ambos extremos están usando .NET. Cualquier interoperabilidad está fuera de la ventana con este enfoque.

+0

+1 Explicación de datos serializados –

Cuestiones relacionadas