第2章 服务契约
通过前一章的介绍,我们知道ServiceContract特性能够将接口(或者类)公开为面向服务的契约,允许开发者使用诸如C#语言进行编程,把类似于接口这样的语法结构公开为WCF契约和服务。本章首先会讨论如何通过操作重载与契约层级,为两种迥然不同的编程模型建立关联。然后会介绍一些简单而又强大的设计和分离服务契约的技术与指导原则。在本章末尾介绍了如何通过编程方式在运行时实现与契约元数据的交互。
操作重载
诸如C++和C#等编程语言都支持方法重载,即允许具有相同名称的两个方法可以定义不同的参数。例如,如下的C#接口就是有效的定义:
interface ICalculator { int Add(int arg1,int arg2); double Add(double arg1,double arg2); }
|
然而,基于WSDL的操作却不支持操作重载。因此,在编译如下的契约定义时,装载服务宿主就会抛出InvalidOperationException异常:
//无效的契约定义: [ServiceContract] interface ICalculator { [OperationContract] int Add(int arg1,int arg2); [OperationContract] double Add(double arg1,double arg2); }
|
但是,我们可以手动地启用操作重载。实现的窍门就是使用OperationContract特性的Name属性,为操作指定别名:
[AttributeUsage(AttributeTargets.Method)] public sealed class OperationContractAttribute : Attribute { public string Name {get;set;} //更多成员 }
|
我们需要同时为服务与客户端的操作指定别名。在服务端,要为重载的操作提供唯一的标识名,如例2-1所示。
例2-1:服务端的操作重载
[ServiceContract] interface ICalculator { [OperationContract(Name = "AddInt")] int Add(int arg1,int arg2); [OperationContract(Name = "AddDouble")] double Add(double arg1,double arg2); }
|
当客户端导入契约并生成代理时,导入的操作就会包含定义的别名:
[ServiceContract] public interface ICalculator { [OperationContract] int AddInt(int arg1,int arg2); [OperationContract] double AddDouble(double arg1,double arg2); } public partial class CalculatorClient : ClientBase<ICalculator>,ICalculator { public int AddInt(int arg1,int arg2) { return Channel.AddInt(arg1,arg2); } public double AddDouble(double arg1,double arg2) { return Channel.AddDouble(arg1,arg2); } //代理的其余内容 }
|
客户端虽然可以使用生成的代理和契约,但我们还需要进行修改,使客户端代码支持操作重载。方法是将导入的代理与契约的方法名修改为重载的名称,并确保代理类能够使用重载方法调用内部代理,例如:
public int Add(int arg1,int arg2) { return Channel.Add(arg1,arg2); }
|
最后,在客户端使用导入契约的Name属性,指定别名并重载方法,使它与导入的操作名保持一致,如例2-2所示。
例2-2:客户端操作重载
[ServiceContract] public interface ICalculator { [OperationContract(Name = "AddInt")] int Add(int arg1,int arg2); [OperationContract(Name = "AddDouble")] double Add(double arg1,double arg2); } public partial class CalculatorClient : ClientBase<ICalculator>,ICalculator { public int Add(int arg1,int arg2) { return Channel.Add(arg1,arg2); } public double Add(double arg,double arg2) { return Channel.Add(arg1,arg2); } //代理的其余内容 }
|
现在,通过操作重载,客户端就能够提供更加自然与优雅的编程模型,具有良好的可读性
CalculatorClient proxy = new CalculatorClient(); int result1 = proxy.Add(1,2); double result2 = proxy.Add(1.0,2.0); proxy.Close();
|
【责任编辑:
雪花 TEL:(010)68476606-8007】