系列文章導航:
WCF從理論到實踐(1):揭開神秘面紗
WCF從理論到實踐(2):決戰紫禁之巔
WCF從理論到實踐(3):八號當鋪之黑色契約
WCF從理論到實踐(4):路在何方
WCF從理論到實踐(5):Binding細解
WCF從理論到實踐(6):WCF架構
WCF從理論到實踐(7):消息交換模式
WCF從理論到實踐(8):事件廣播
WCF從理論到實踐(9):實例模式和對象生命周期
WCF從理論到實踐(10):異常處理
WCF從理論到實踐(11)-異步
WCF從理論到實踐(12):事務
WCF從理論到實踐(13):事務投票
WCF從理論到實踐(14):WCF解決方案模板
WCF從理論到實踐(15):響應變化
WCF從理論到實踐(16):操作重載(帶視頻+ppt+源碼)
WCF從理論到實踐(17):OO大背離(帶視頻+ppt+源碼)
如果您懶得看下面的文字,您按下面的提示下載視頻教程,里面還有ppt和源代碼
本文目的:
閱讀本文,您能了解以下知識
- 什么是操作重載?操作重載有什么好處
- WCF的服務端如何解決操作重載的問題?
- WCF的客戶端如何解決操作重載問題?
- 小結
什么是操作重載?操作重載有什么好處
重載指的是在同一個類,接口或者結構中包含多個同名的 方法,而這些方法的參數列表或者返回值各不相同.使用它的好處在于提高模型的強壯性和通用性,使模型在一個可維護統一高度上運行,其功能和返回依賴于傳遞的參數. 在傳統的程序開發中,我們程序員經常使用這種技術,比如一個有一個功能既能夠計算兩個整數的和,又能計算兩個雙精度數的和,這樣的需求,我們往往會按下面這樣書寫代碼:
public int Add(int a, int b)



{

return a + b;

}

public double Add(double a, double b)



{

return a + b;

}


而在WCF中,還能不能這么干呢?不能!為什么呢?WCF中無論是服務端還是客戶端,如果單拿出來一個都是支持操作重載的,但是客戶端代理生成的依據卻是WSDL,而WSDL是不支持操作重載的,另外客戶端調用服務端的一個操作的必須先要確定兩個要素:1)操作所屬的服務是哪一個?2) 操作在服務中的名稱是什么?這樣的話,向傳統應用程序程序那樣重載就會出現問題!
WCF的服務端如何解決操作重載的問題?
如果按照下面的代碼來實現一個服務:
服務契約
[ServiceContract]

public interface IService



{

[OperationContract]

int Add(int a, int b);


[OperationContract]

double Add(double a, double b);

}


而服務實現為:
public class Service : IService



{

public int Add(int a, int b)



{

return a + b;

}

public double Add(double a, double b)



{

return a + b;

}

}


那么,在編譯的時候,是沒有錯誤的。此時,我們再按照下面的代碼實現一個托管:
using(ServiceHost host = new ServiceHost(typeof(Service),new Uri("net.tcp://127.0.0.1:12345")))



{

NetTcpBinding bind = new NetTcpBinding();

host.AddServiceEndpoint(typeof(IService), bind, "");

//下面代碼的目的是添加一個MeatedataExchage的EndPoint

BindingElement bindElement = new TcpTransportBindingElement();

CustomBinding metaBind = new CustomBinding(bindElement);

ServiceMetadataBehavior metaBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();

if (metaBehavior == null)



{

metaBehavior = new ServiceMetadataBehavior();

host.Description.Behaviors.Add(metaBehavior);

}

host.AddServiceEndpoint(typeof(IMetadataExchange), metaBind, "MEX");

host.Open();

Console.WriteLine("服務已經運行!");

Console.Read();

}


隨后,我們啟動托管程序,發現代碼在運行到ServiceHost host = new ServiceHost(typeof(Service),new Uri("net.tcp://127.0.0.1:12345"))的時候,發生如下的異常:
這個異常提示我們,同一個協定之中不能存在相同的操作,在WCF中操作重載是不顯示適用的。而且問題不在于編譯階段,而在于托管階段。
但是我們能通過一些改進的手段來獲取WCF對操作重載的支持。我們先把服務契約的定義更改為如下的代碼:
[ServiceContract]

public interface IService



{

[OperationContract(Name="AddInt")]

int Add(int a, int b);


[OperationContract(Name="AddDouble")]

double Add(double a, double b);

}


此時,我們在啟動托管,發現已經能夠正常運行了
到此,我們是不是就完美的解決了WCF中關于操作重載的問題呢?不,還沒有,因為WCF既包含服務端,又包含客戶端,我們當前已經將服務端順利的運行起來了。總結一下,就說服務端不是顯示支持重載的,重載的操作各自的別名必須更不一致。
WCF的客戶端如何解決操作重載問題?
但客戶端呢?下面就來看下客戶端對操作重載的反應。
要想實現客戶端,我們創建一個Console的客戶端應用程序,然后需要用SvcUtiil.exe生成代理類,方法如下
打開Proxy.cs,我們會發現代理的代碼如下:

默認生成的代理類代碼
//------------------------------------------------------------------------------

//

// 此代碼由工具生成。

// 運行庫版本:2.0.50727.1433

//

// 對此文件的更改可能會導致不正確的行為,并且如果

// 重新生成代碼,這些更改將會丟失。

//

//------------------------------------------------------------------------------




[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IService")]

public interface IService



{


[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/AddInt", ReplyAction="http://tempuri.org/IService/AddIntResponse")]

int AddInt(int a, int b);


[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/AddDouble", ReplyAction="http://tempuri.org/IService/AddDoubleResponse")]

double AddDouble(double a, double b);

}


[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

public interface IServiceChannel : IService, System.ServiceModel.IClientChannel



{

}


[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

public partial class ServiceClient : System.ServiceModel.ClientBase<IService>, IService



{


public ServiceClient()



{

}


public ServiceClient(string endpointConfigurationName) :

base(endpointConfigurationName)



{

}


public ServiceClient(string endpointConfigurationName, string remoteAddress) :

base(endpointConfigurationName, remoteAddress)



{

}


public ServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :

base(endpointConfigurationName, remoteAddress)



{

}


public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :

base(binding, remoteAddress)



{

}


public int AddInt(int a, int b)



{

return base.Channel.AddInt(a, b);

}


public double AddDouble(double a, double b)



{

return base.Channel.AddDouble(a, b);

}

}


仔細觀察代理的代碼不難發現,代理中的服務契約以及服務實現的操作與服務端定義的想比,有所更改。而且對于代理類來說,已經沒有了重載,雖然此代理類能夠被正常使用,但是卻沒有了重載的好處,如何更改代理類,才能使其也有重載是下面要研究的問題。
我們將代理中的服務契約IService中的操作定義修改為:
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/AddInt", ReplyAction="http://tempuri.org/IService/AddIntResponse",Name="AddInt")]

int Add(int a, int b);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/AddDouble", ReplyAction="http://tempuri.org/IService/AddDoubleResponse",Name="AddDouble")]

double Add(double a, double b);


然后將服務實現ServiceClient中的方法更改為:
public int Add(int a, int b)



{

return base.Channel.Add(a, b);

}

public double Add(double a, double b)



{

return base.Channel.Add(a, b);

} 
創建一個Console的客戶端應用程序,然后將修改后的Proxy.cs拷貝到其中,實現客戶端調用,代碼如下:
IService ws = new ServiceClient(new NetTcpBinding(), new EndpointAddress("net.tcp://127.0.0.1:12345"));

using (ws as IDisposable)



{

Console.WriteLine(ws.Add(1,2).ToString());

Console.WriteLine(ws.Add(1.3, 2.4).ToString());

}

Console.Read(); 
將解決方案設置為多啟動項目,并啟動托管和客戶端,出現下面的結果:
說明客戶端和服務端已經成功通訊。從上面實現客戶端的方法來看,客戶端想實現重載,也必須保證重載操作的別名要有服務端的相匹配,其各不相同。
小結
從本文可以看出,WCF編程雖然保持了大部分原有編程模式,也繼承了原有模式足夠多好的做法,但是限于分布式開發與傳統應用程序的差異,在有些細節上還是有區別的,比如本文所討論的操作重載問題,其實還有很多類似問題,比如繼承的差異,序列化的差異,處理集合的差異等等。要想真正的掌握這些問題,必須要深刻了解分布式開發的特型。加深對服務交互,類型轉換,封送等WCF架構方面的理解。以下幾點是對本文的總結:
1) 對于WCF中的服務端,對服務契約和服務實現不支持顯示的操作重載,但可以通過設置重載操作的別名來改善這種狀況
2) 對于WCF客戶端,默認情況下,生成的代理也不支持操作重載,想要改變這種狀況也必須依賴于別名。
3) 我推薦的做法是在服務端還是要用別名的方式支持操作重載,在客戶端手動更改代理類,以便也支持操作重載。
視頻,課件以及源碼下載
< body>