WCF分布式开发步步为赢(5)服务契约与操作重载
【3】代码实现分析:
下面我们来给出一个具体的WCF服务实现操作重载,包括服务定义、宿主配置、客户端引用和测试的完整过程。
【3.1】服务契约:
定义了服务契约IWCFOverLoadingService,分别给出SayHelloOverLoading操作契约的3种不同定义和WCFService服务类里的实现。具体代码如下:
//1.服务契约,操作契约重载
[ServiceContract(Namespace = "http://www.cnblogs.com/frank_xl/")]
public interface IWCFOverLoadingService
{
//操作契约
[OperationContract(Name = "SayHelloOverLoading1")]
string SayHelloOverLoading();
//操作契约
[OperationContract(Name = "SayHelloOverLoading2")]
string SayHelloOverLoading(string name);
//操作契约
[OperationContract(Name = "SayHelloOverLoading3")]
string SayHelloOverLoading(string firstName, string lastName);
}
//2.服务类,集成接口。实现契约
public class WCFService : IWCFOverLoadingService
{
//实现接口定义的方法
public string SayHelloOverLoading()
{
Console.WriteLine("Hello! ,This an overloading demo for WCF Service ");
return "Hello! This an overloading demo for WCF Service ";
}
//实现接口定义的方法
public string SayHelloOverLoading(string name)
{
Console.WriteLine("Hello! {0},This an overloading demo WCF Service ", name);
return "Hello! " + name + ", This an overloading demo for WCF Service ";
}
//实现接口定义的方法
public string SayHelloOverLoading(string firstName, string lastName)
{
Console.WriteLine("Hello! {0} {1},This an overloading demo WCF Service", firstName, lastName);
return "Hello! " + firstName + " " + lastName + ", This an overloading demo for WCF Service "; ;
}
}
[ServiceContract(Namespace = "http://www.cnblogs.com/frank_xl/")]
public interface IWCFOverLoadingService
{
//操作契约
[OperationContract(Name = "SayHelloOverLoading1")]
string SayHelloOverLoading();
//操作契约
[OperationContract(Name = "SayHelloOverLoading2")]
string SayHelloOverLoading(string name);
//操作契约
[OperationContract(Name = "SayHelloOverLoading3")]
string SayHelloOverLoading(string firstName, string lastName);
}
//2.服务类,集成接口。实现契约
public class WCFService : IWCFOverLoadingService
{
//实现接口定义的方法
public string SayHelloOverLoading()
{
Console.WriteLine("Hello! ,This an overloading demo for WCF Service ");
return "Hello! This an overloading demo for WCF Service ";
}
//实现接口定义的方法
public string SayHelloOverLoading(string name)
{
Console.WriteLine("Hello! {0},This an overloading demo WCF Service ", name);
return "Hello! " + name + ", This an overloading demo for WCF Service ";
}
//实现接口定义的方法
public string SayHelloOverLoading(string firstName, string lastName)
{
Console.WriteLine("Hello! {0} {1},This an overloading demo WCF Service", firstName, lastName);
return "Hello! " + firstName + " " + lastName + ", This an overloading demo for WCF Service "; ;
}
}
【3.2】托管宿主:
自定义托管宿主使用配置文件来定义服务的终结点和元数据交换节点,服务的交换行为等其他属性也在配置文件里给出,我们配置了三种不同的数据服务通信方式,分别是http、tcp、IPC.具体配置信息如下:
<services>
<service behaviorConfiguration="WCFService.WCFServiceBehavior" name="WCFService.WCFService">
<endpoint
address="http://localhost:9001/WCFService"
binding="wsHttpBinding"
contract="WCFService.IWCFOverLoadingService">
endpoint>
<endpoint
address="net.tcp://localhost:9002/WCFService"
binding="netTcpBinding"
contract="WCFService.IWCFOverLoadingService">
endpoint>
<endpoint
address="net.pipe://localhost/WCFService"
binding="netNamedPipeBinding"
contract="WCFService.IWCFOverLoadingService">
endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexNamedPipeBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/"/>
<add baseAddress="net.tcp://localhost:9002/"/>
<add baseAddress="net.pipe://localhost/"/>
baseAddresses>
host>
service>
services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.WCFServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
behavior>
serviceBehaviors>
behaviors>
<service behaviorConfiguration="WCFService.WCFServiceBehavior" name="WCFService.WCFService">
<endpoint
address="http://localhost:9001/WCFService"
binding="wsHttpBinding"
contract="WCFService.IWCFOverLoadingService">
endpoint>
<endpoint
address="net.tcp://localhost:9002/WCFService"
binding="netTcpBinding"
contract="WCFService.IWCFOverLoadingService">
endpoint>
<endpoint
address="net.pipe://localhost/WCFService"
binding="netNamedPipeBinding"
contract="WCFService.IWCFOverLoadingService">
endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<endpoint address="mex" binding="mexNamedPipeBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/"/>
<add baseAddress="net.tcp://localhost:9002/"/>
<add baseAddress="net.pipe://localhost/"/>
baseAddresses>
host>
service>
services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.WCFServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
behavior>
serviceBehaviors>
behaviors>
【3.3】客户端服务引用:
我们来分别添加对服务端的引用,首先启动托管宿主程序。然后使用Visual Studio2008工具直接添加服务引用,你也可以使用svcUtil.exe工具,如图所示:
客户端输入服务的基地址,查找服务,成功够我们可以看到服务契约的信息,这里显示的3个操作名称已经不同,实际上这里给出的是三个不同名称的服务方法。输入命名空间,确定即可完成。
【3.4】代理代码:
客户端反序列化生成的服务契约等信息,我们查看操作契约对应的客户端方法名称以及改变,这样一来,客户端就没有实现对应的方法重载,也就不能使用重载带来的优势,也即是编译时多态的特性。手动更改客户端服务代理类和服务契约代码,使之支持操作方法重载,代码如下:
public interface IWCFOverLoadingService {
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading1" ,Action="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1", ReplyAction="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1Respon" +
"se")]
string SayHelloOverLoading();
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading2", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2Respon" +
"se")]
string SayHelloOverLoading(string name);
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading3", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3Respon" +
"se")]
string SayHelloOverLoading(string firstName, string lastName);
}
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading1" ,Action="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1", ReplyAction="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1Respon" +
"se")]
string SayHelloOverLoading();
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading2", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2Respon" +
"se")]
string SayHelloOverLoading(string name);
[System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading3", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3Respon" +
"se")]
string SayHelloOverLoading(string firstName, string lastName);
}
这样我们客户端方法也支持操作方法的重载特性。
【3.5】客户端测试代码:
为了测试操作契约,我们在客户端应用里添加了部分的测试代码,这里为了测试服务端定义的不同的操作。我们分组按照协议给出了测试的代码:
//实例化客户端服务代理Tcp
ServiceOverLoadingTcp.WCFOverLoadingServiceClient wcfServiceProxyTcp =
new ServiceOverLoadingTcp.WCFOverLoadingServiceClient("WSHttpBinding_IWCFOverLoadingService1");
Console.WriteLine("Test call service using TCP--------------------.");
//通过代理调用SayHelloOverLoading服务,分别传递不同的参数,进行测试
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading());
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Frank Xu Lei"));
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Lei", "Xu"));
//实例化客户端服务代理Http
ServiceOverLoadingHttp.WCFOverLoadingServiceClient wcfServiceProxyHttp =
new ServiceOverLoadingHttp.WCFOverLoadingServiceClient("NetTcpBinding_IWCFOverLoadingService");
Console.WriteLine("Test call service using Http-------------------");
//通过代理调用SayHelloOverLoading服务,分别传递不同的参数,进行测试
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading());
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Frank Xu Lei"));
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Lei", "Xu"));
//Debuging
Console.WriteLine("Press any key to continue");
Console.Read();
ServiceOverLoadingTcp.WCFOverLoadingServiceClient wcfServiceProxyTcp =
new ServiceOverLoadingTcp.WCFOverLoadingServiceClient("WSHttpBinding_IWCFOverLoadingService1");
Console.WriteLine("Test call service using TCP--------------------.");
//通过代理调用SayHelloOverLoading服务,分别传递不同的参数,进行测试
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading());
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Frank Xu Lei"));
Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Lei", "Xu"));
//实例化客户端服务代理Http
ServiceOverLoadingHttp.WCFOverLoadingServiceClient wcfServiceProxyHttp =
new ServiceOverLoadingHttp.WCFOverLoadingServiceClient("NetTcpBinding_IWCFOverLoadingService");
Console.WriteLine("Test call service using Http-------------------");
//通过代理调用SayHelloOverLoading服务,分别传递不同的参数,进行测试
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading());
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Frank Xu Lei"));
Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Lei", "Xu"));
//Debuging
Console.WriteLine("Press any key to continue");
Console.Read();