我正在尝试使用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得到了我应该做什么或者我错过了什么......
谢谢!
答案 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
属性不会神奇地将数据传输对象转换为服务。