添加一个WCF文件,会自动生成两个文件,一个cs后缀一个svc后缀.
cs后缀为对接口的定义.
svc后缀为实现接口的服务.
下面的代码为对接口的定义,代码中对契约和序列化进行了详细解释.
注意:客户端在创建完服务器端的对象时,不会对属性进行赋值.
即跟属性对应的变量赋值语句不会被执行(已跟踪).【不知道为什么???】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
![]()
namespace WcfService_AX
![]()
![]()
{
//【服务契约】
//(可重新命名,默认为相关接口或方法名)
[ServiceContract(Name = "ServiceName")]
public interface IService_AX
![]()
{
//可操作的方法的契约
[OperationContract(Name = "OperationA")]
string DoWork();
[OperationContract]
string OperateSerializableType(A a);
[OperationContract]
B OperateDataContractType(B b);
//参数通过Channel传递Message,返回类型必须与参数一致
[OperationContract]
C OperateMessageType(C c);
}
![]()
![]()
//--------复杂对象序列化--------
//1.使用Serializable属性.
//该类可以被序列化,不论可访问性如何
//无法对命名规范或数据类型进行控制
[Serializable]
public class A
![]()
{
private int i;
public string j;
private DateTime k;
}
![]()
![]()
//2.使用DataContract属性.
//【数据契约】
//★★★★★★变量赋完初值在客户端会丢失,Why?★★★★★★
//能明确成员是否参与序列化
//应用与域或属性
[DataContract]
public class B
![]()
{
//Name:Client端看到的Name
//IsRequired:是否允许为空
//Order:在数据包中与其它成员的相对位置
[DataMember(Name = "AX", IsRequired = false, Order = 0)]
private int i = 1;
[DataMember]
private string name = "My name is AX.";
![]()
[DataMember]
public string Name
![]()
{
get
![]()
{
return name;
}
set
![]()
{
name = value;
}
}
//在构造中赋初值也不行,到Client端会丢失
public B()
![]()
{
name = "Construct";
}
}
![]()
//3.实现IXmlSerializable接口
//手动编写XML信息
//(不实用,很少有这种需求,所以没有例子)
//-------------------------------------------------
![]()
//【消息契约】
//可以指定成员放在消息的head或body中
//添加自定义头
//控制消息是否被包装
//控制签名或加密
[MessageContract(IsWrapped=true,ProtectionLevel=System.Net.Security.ProtectionLevel.Sign)]
public class C
![]()
{
private int i=5;
[MessageHeader]
public int MyProperty
![]()
{
get
![]()
{
return i;
}
set
![]()
{
i = value;
}
}
![]()
[MessageBodyMember]
public int Item;
}
![]()
}
![]()
实现接口的服务代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
![]()
namespace WcfService_AX
![]()
![]()
{
public class Service_AX : IService_AX
![]()
{
public string DoWork()
![]()
{
return "Hello World!";
}
![]()
![]()
public string OperateSerializableType(A a)
![]()
{
a.j = "OK";
return "You load the Method:OperateSerializableType--Parameter type is " + a.GetType().ToString() + a.j;
}
![]()
![]()
public B OperateDataContractType(B b)
![]()
{
b.Name += "--Operation has complished!--";
return b;
}
![]()
public C OperateMessageType(C c)
![]()
{
c.MyProperty++;
return c;
}
![]()
}
}
![]()
客户端调用代码(不会调用的见上篇)
protected void Page_Load(object sender, EventArgs e)
![]()
{
SR.ServiceName proxy = new SR.ServiceNameClient();
Response.Write(proxy.OperationA()+"<br/>");
![]()
SR.A a = new SR.A();
a.j = "Hi";
Response.Write(proxy.OperateSerializableType(a) + "<br/>");
![]()
![]()
SR.B b = new SR.B();
Response.Write(b.name1+"<br/>");
Response.Write(b.Name + "<br/>");
Response.Write(proxy.OperateDataContractType(b).Name + "<br/>");
![]()
![]()
SR.C c = new SR.C();
Response.Write(c.MyProperty.ToString()+"<br/>");
Response.Write(proxy.OperateMessageType(c).MyProperty.ToString() + "<br/>");
}
其中有意思的是name变量变成了name1,元数据为
namespace SR
![]()
![]()
{
[Serializable]
[DebuggerStepThrough]
[GeneratedCode("System.Runtime.Serialization", "3.0.0.0")]
[DataContract(Name = "B", Namespace = "http://schemas.datacontract.org/2004/07/WcfService_AX")]
public class B : IExtensibleDataObject, INotifyPropertyChanged
![]()
{
public B();
![]()
[DataMember(Order = 2)]
![]()
public int AX
{ get; set; }
![]()
public ExtensionDataObject ExtensionData
{ get; set; }
[DataMember]
![]()
public string Name
{ get; set; }
[DataMember(Name = "name")]
![]()
public string name1
{ get; set; }
![]()
public event PropertyChangedEventHandler PropertyChanged;
![]()
protected void RaisePropertyChanged(string propertyName);
}
}
输出结果
Hello World!
You load the Method:OperateSerializableType--Parameter type is WcfService_AX.AOK
--Operation has complished!--
0
1
感觉比较简单,就不附代码下载了.
博客园→斧头帮少帮主