WCF服务编程学习笔记之----服务契约
1:服务契约的操作符重载
诸如C++和C#等编程语言都支持方法重载,但是,基于WSDL的操作不支持操作重载,如果在WCF中定义重载函数,在启动服务时就会抛出异常InvalidOperationException,异常信息如下:“同一个协定中不能存在两个名称相同的操作,类型为 ServiceContractSample.IServiceContracOverload 的方法 Add 和 Add 违反了此规则。可以通过更改方法名称或使用 OperationContractAttribute 的 Name 属性更改其中一个操作的名称。”
但是WCF可以手动启用操作符重载,实现的方式就是在OperationContract特性的Name特性,为操作指定别名。代码如下:
服务端重载接口的定义:
[ServiceContract]
public interface IServiceContracOverload
{
[OperationContract(Name="AddInt")]//给此操作契约特性定义名称为AddInt
int Add(int x, int y);
[OperationContract(Name="AddDouble")]//给此操作契约特性定义名称为AddDouble
double Add(double x, double y);
}
客户端生成引用后代码:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="OverloadServiceReference.IServiceContracOverload")]
public interface IServiceContracOverload {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IServiceContracOverload/AddInt", ReplyAction="http://tempuri.org/IServiceContracOverload/AddIntResponse")]
int AddInt(int x, int y);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IServiceContracOverload/AddDouble", ReplyAction="http://tempuri.org/IServiceContracOverload/AddDoubleResponse")]
double AddDouble(double x, double y);
}
2:服务契约的继承
服务端契约接口支持继承功能,但是要在每个层次的接口上都要加上[ServiceContract]的特性标记,这样一个单独的服务类就可以实现所有契约层次的接口功能。对外提供公开一个单独的终结点。
但时,有一点,在生成客户端代理类的时候,客户端契约将不在维持原来的层次关系,它会取消所有的层次,放在单独的一个客户端契约类中。在这个契约类中,包含了从上至下所有的接口定义。
如果使用了OperationContract特性中的Action和ReplyAction这两个属性,它会表明此功能是在服务端是属于哪个接口的。
实例:
服务端定义接口如下:
[ServiceContract]
public interface IServiceContractInherited : IServiceContractParent
{
[OperationContract]
void DoWork();
}
[ServiceContract]
public interface IServiceContractParent
{
[OperationContract]
void ParentMethod();
}
实现类如下:
public class ServiceContractInherited : IServiceContractInherited
{
#region IServiceContractInherited 成员
public void DoWork()
{
Trace.WriteLine("working...");
}
public void ParentMethod()
{
Trace.WriteLine("ParentMethod working ...");
}
#endregion
}
在客户端生成的代理类如下:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="InheritedServiceReference.IServiceContractInherited")]
public interface IServiceContractInherited {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IServiceContractParent/ParentMethod", ReplyAction="http://tempuri.org/IServiceContractParent/ParentMethodResponse")]
void ParentMethod();
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IServiceContractInherited/DoWork", ReplyAction="http://tempuri.org/IServiceContractInherited/DoWorkResponse")]
void DoWork();
}
在客户端的Action和ReplyAction这两属性中,标明了ParentMethod()是属于IServiceContractParent接口内的函数,DoWork()是属于IServiceContractInherited接口内的函数。
如果想保持契约的层次级别,需要自己修改客户端代理类。
3:服务契约的实现类不支持继承多个契约
在服务契约的服务实现类中,如果继承两个或多个接口,这种情况是不支持的,在生成客户端代理类时,生成的客户端契约只是公开的终结点指定的服务契约接口内的功能。
实例如下:
两个服务契约接口:
[ServiceContract]
public interface IServiceMultiplyInherited
{
[OperationContract]
void DoWork();
}
[ServiceContract]
public interface ISeviceInherited2
{
[OperationContract]
void Test();
}
服务契约的实现类:
public class ServiceMultiplyInherited : IServiceMultiplyInherited, ISeviceInherited2
{
#region IServiceContractParent 成员
public void DoWork()
{
Trace.WriteLine("working...");
}
public void Test()
{
Trace.WriteLine("Testing...");
}
#endregion
}
服务的配置
<service behaviorConfiguration="ServiceContractSample.ServiceMultiplyInheritedBehavior"
name="ServiceContractSample.ServiceMultiplyInherited">
<endpoint address="" binding="wsHttpBinding" contract="ServiceContractSample.ISeviceInherited2">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/ServiceContractSample/ServiceMultiplyInherited/" />
</baseAddresses>
</host>
</service>
在生成的客户端代理类中,生成的客户端契约中只包含ISeviceInherited2接口内的功能。
代码如下:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] [System.ServiceModel.ServiceContractAttribute(ConfigurationName="MultiplyServiceReference.ISeviceInherited2")]
public interface ISeviceInherited2 {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISeviceInherited2/Test", ReplyAction="http://tempuri.org/ISeviceInherited2/TestResponse")]
void Test();
}