WCF将对象返回给客户端

时间:2010-11-06 06:25:01

标签: wcf web-services serialization object

我正在尝试使用WCF,我想我已经遇到了障碍。我的问题是,我可以从“客户”中拨打Add(double,double)getPerson()。但是,我无法调用任何Person对象的方法。我用裸方法剥离了类。以下是我的代码片段,请让我知道我做错了什么..

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"

我猜测我的Person类声明出了什么问题..但是dint得到了我应该做什么或者我错过了什么......

谢谢!

2 个答案:

答案 0 :(得分:11)

是的,你遇到了障碍--WCF是一个基于消息的系统,只能以文本或二进制格式交换序列化数据,无论是XML还是JSON。它确实传递“完整”的.NET对象及其全部功能,如方法和所有这些(应该如何?它的设计是可互操作的,我不喜欢看看Ruby或PHP客户端如何在.NET对象上调用方法。

WCF的目的不是为了能够远程访问对象 - 它只是在客户端和服务器之间传递消息。因此,您可以在XML模式中表达的任何内容(原子类型,继承和组合等)都可以序列化并在双方之间发送。

任何无法在XML模式中建模的东西 - 如泛型,接口,方法/代码 - 都无法在客户端和服务器之间传递。

如果您控制通信的两端并且它们都是基于.NET的,那么有办法解决这个问题。基本上,您必须将服务合同和所有数据合同(所有类)放入一个单独的程序集中,然后从服务器(实现服务合同)和调用合同的客户端引用。您可以告诉WCF重用已引用的程序集中已存在的类型,在这种情况下,客户端将从您的公共共享程序集中重用现成的Person类(具有其所有.NET优点)而不是重新创建客户端数据代理。通过这个技巧,您可以让WCF通过线路发送序列化消息,但在客户端,您将重新创建一个包含所有方法的完整.NET对象。

再次说明:只要您控制通信的两端,并且两端都使用.NET,这就行得很好。使用这种方法可以实现任何互操作性。

答案 1 :(得分:9)

您正在使用Person类型混合两个概念 - 您正在做的事情将无效。

您在DataContract类型上添加了Person属性。这是正确的,因为您有一个返回Person的服务。 Person对象将被序列化并返回给您的服务客户端(在这种情况下为CalculatorClient)。

您应该像这样定义Person

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

在你的计算器服务中:

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

这是因为您的Person对象的工作是保存数据,并将其从服务器传送到客户端。定义方法/操作不是它的工作,而应该在您的服务类中完成(例如CalculatorService)。添加OperationContract属性不会神奇地将数据传输对象转换为服务。