[WCF] Contract
在 WCF 中,所有的服务都通过契约供外部进行调用。所谓契约,就是描述服务的一种平台无关的、标准的方式。目前,在 WCF 中定义了四种契约。
l 服务契约(Service contract)
描述了客户端能够调用服务的哪些操作。
l 数据契约(Data contract)
描述了哪些数据类型能够在客户端和服务间传输。CLR 数据类型都默认地被添加上了数据契约,当然也可以很方便的为自定义类型添加数据契约。
l 异常契约(Fault contract)
描述了在服务中可能出现的异常以及服务如何处理、传播异常。
l 消息契约(Message contract)
指定了该契约的消息能够直接与服务进行交互。
服务契约
using System.ServiceModel;
namespace Anrs.Service
{
[ServiceContract()]
public interface IAnrsServiceContract
{
[OperationContract()]
string GetFullName(string author);
[OperationContract()]
string GetFamilyName(string author);
}
public class AnrsService : IAnrsServiceContract
{
public string GetFullName(string author)
{
return author.Replace('.', ' ');
}
public string GetFamilyName(string author)
{
return author.Split('.')[2];
}
}
}
服务契约映射到 CLR 接口类型,并且对于契约来讲,可访问性是无关紧要的,因为“可访问性”本身就是一个 CLR 的概念,在 WCF 中是不存在该概念的。没有实现 ServiceContract 特性的接口对客户端就是不可见的,这就暗合了 SO 的“边界清晰”原则。另外,必须明确告诉 WCF 那些方法是 ServiceContract 的一部分(使用 OperationContract 特性,没有应用 OperationContract 特性的方法将不被视为服务契约的一部分),也就是说这些方法能够被客户端调用。不过,OperationContract 特性只能应用到方法上,对 properties/indexers/events 来讲都是无效的。
单个方法也可以实现多个应用了 ServiceContract 特性的接口。
using System.ServiceModel;
namespace Anrs.Service
{
[ServiceContract()]
public interface IAnrsServiceContract1
{
[OperationContract()]
string GetFullName(string author);
[OperationContract()]
string GetFamilyName(string author);
}
[ServiceContract()]
public interface IAnrsServiceContract2
{
[OperationContract()]
void SaveAuthor(string author);
}
public class AnrsService : IAnrsServiceContract1, IAnrsServiceContract2
{
public string GetFullName(string author)
{
return author.Replace('.', ' ');
}
public string GetFamilyName(string author)
{
return author.Split('.')[2];
}
public void SaveAuthor(string author)
{
Console.WriteLine("Save {0} to database", author);
}
}
}
名字1和命名空间
可以也应该为 ServiceContract 定义一个命名空间(命名空间的好处就不用多说了),象下面这样:
public interface IAnrsServiceContract1
如果没有明确指定命名空间,WCF 会为 ServiceContract 指定一个默认的命名空间 http://tempuri.org 。ServiceContract 的名字最好和接口的名字相同。
public interface IAnrsServiceContract1
同样的,也可以为 OperationContract 指定名字。
public interface IAnrsServiceContract1
{
[OperationContract(Name="GetFullName")]
string GetFullName(string author);
1. 为 ServiceContract/OperationContract 指定不同于 interface/method 实际名字的别名会影响到发送到客户端的元数据(metadata)。