WCF开发框架形成之旅--WCF应用常见问题处理
本文繼續(xù)前面幾篇關(guān)于WCF開(kāi)發(fā)框架的隨筆,繼續(xù)介紹WCF的一些經(jīng)驗(yàn)和知識(shí),其中主要介紹在使用WCF開(kāi)發(fā)中碰到的問(wèn)題以及解決方法,為自己做個(gè)記號(hào),也為后來(lái)者提供解決思路,其中包括有動(dòng)態(tài)修改 WCF配置內(nèi)容、規(guī)范WCF客戶端的調(diào)用和處理。?
1、 動(dòng)態(tài)修改WCF配置內(nèi)容
由于在軟件登錄界面中,需要提供用戶切換內(nèi)網(wǎng)、外網(wǎng)的功能,而配置文件中內(nèi)外網(wǎng)的地址配置是不一樣的,因此需要?jiǎng)討B(tài)修改應(yīng)用程序的配置文件,然后更新其中節(jié)點(diǎn)內(nèi)容,界面如下所示。
?
修改WCF節(jié)點(diǎn)的C#代碼如下所示
private?void?ChangeConfig()?????????{
????????????bool?isIntranet?=?radNetType.EditValue.ToString()?==?"內(nèi)網(wǎng)";
????????????if?(isIntranet)
????????????{
????????????????UpdateConfig("192.168.1.2",?"8002");
????????????}
????????????else
????????????{
????????????????UpdateConfig("219.136.1.2",?"8002");
????????????}
????????}
????????private?void?UpdateConfig(string?serverIPAddress,?string?serverPort)
????????{
????????????//Configuration?config?=?ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);??
????????????Configuration?config?=?ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
????????????ConfigurationSectionGroup?sct?=?config.SectionGroups["system.serviceModel"];
????????????ServiceModelSectionGroup?serviceModelSectionGroup?=?sct?as?ServiceModelSectionGroup;
????????????ClientSection?clientSection?=?serviceModelSectionGroup.Client;
????????????foreach?(ChannelEndpointElement?item?in?clientSection.Endpoints)
????????????{
????????????????string?pattern?=?"://.*/";
????????????????string?address?=?item.Address.ToString();
????????????????if?(address.ToLower().Contains("localhost"))
????????????????????return;
????????????????string?replacement?=?string.Format("://{0}:{1}/",?serverIPAddress,?serverPort);
????????????????address?=?Regex.Replace(address,?pattern,?replacement);
????????????????item.Address?=?new?Uri(address);
????????????}
????????????config.Save(ConfigurationSaveMode.Modified);
????????????ConfigurationManager.RefreshSection("system.serviceModel");
????????}
其中為了調(diào)試方便,在修改配置文件代碼里面,判斷地址如果是localhost的則不進(jìn)行修改切換。
?
2、 規(guī)范WCF客戶端的調(diào)用處理。
在創(chuàng)建WCF服務(wù)客戶端實(shí)例的時(shí)候,我們可能會(huì)這樣共創(chuàng)建客戶端并調(diào)用,就是在窗體的頂部,創(chuàng)建一個(gè)該窗體內(nèi)的全局WCF服務(wù)客戶端實(shí)例。
public?partial?class?FrmParkUser?:?BaseDock????{
????????private?DeviceUserServiceClient?client?=?new?DeviceUserServiceClient();
????????public?string?ID?=?string.Empty;
????????public?FrmParkUser()
????????{
????????????InitializeComponent();
????????}
?? ? ? ?.................??
實(shí)際使用wcf客戶端的時(shí)候,我們可能會(huì)這樣調(diào)用。
this.winGridViewPager1.PagerInfo.RecordCount?=?client.GetRecordCount2(where);??? ? ? ? ??this.winGridViewPager1.DataSource?=?client.SearchParkUser(where,?this.winGridViewPager1.PagerInfo);
OK,其實(shí)這樣使用看起來(lái)是沒(méi)什么問(wèn)題的,而且也能順利使用,不過(guò),由于wcf客戶端都有一個(gè)超時(shí)時(shí)間,可能靜止過(guò)了一段時(shí)間,你在界面刷新數(shù)據(jù)的時(shí)候,你會(huì)發(fā)現(xiàn)出現(xiàn)下面的錯(cuò)誤:"通信對(duì)象?System.ServiceModel.Channels.ServiceChannel?無(wú)法用于通信,因?yàn)槠涮幱凇俺鲥e(cuò)”狀態(tài)。"?
或者是一些奇怪的錯(cuò)誤信息。
既然上面的調(diào)用不好,那么我們應(yīng)該如何調(diào)用客戶端呢,有人這樣調(diào)用。
using?(var?client?=?new?SomeWCFServiceClient())?{
????//Do?something?with?the?client?
}??
其實(shí)這樣操作,更不好,也會(huì)出現(xiàn)上面紅色的錯(cuò)誤,微軟建議的調(diào)用方式應(yīng)該是這樣的
try{
????...
????client.Close();
}
catch?(CommunicationException?e)
{
????...
????client.Abort();
}
catch?(TimeoutException?e)
{
????...
????client.Abort();
}
catch?(Exception?e)
{
????...
????client.Abort();
????throw;
}??
但如果調(diào)用頻繁,這樣實(shí)在不雅,管理也非常難受。有沒(méi)有更好的方式,避免出錯(cuò),又能夠正確調(diào)用wcf客戶嗎,當(dāng)然有,下面這樣方式就是比較好的一種解決方案,經(jīng)過(guò)實(shí)際測(cè)試,效果不錯(cuò)。
1、 首先創(chuàng)建一個(gè)擴(kuò)展輔助類,代碼如下所示
///?<summary>????///?WCF服務(wù)包裝類,避免使用Using等方式導(dǎo)致服務(wù)出錯(cuò)的問(wèn)題
????///?</summary>
????public?static?class?WcfExtensions
????{
????????public?static?void?Using<T>(this?T?client,?Action<T>?work)
????????????where?T?:?ICommunicationObject
????????{
????????????try
????????????{
????????????????work(client);
????????????????client.Close();
????????????}
????????????catch?(CommunicationException?e)
????????????{
????????????????client.Abort();
????????????}
????????????catch?(TimeoutException?e)
????????????{
????????????????client.Abort();
????????????}
????????????catch?(Exception?e)
????????????{
????????????????client.Abort();
????????????????throw;
????????????}
????????}
?? ?}???
然后實(shí)際調(diào)用的時(shí)候,如下即可,看起來(lái)還是非常簡(jiǎn)單的,這樣是即需創(chuàng)建的代理客戶端,即使很久不操作,也不會(huì)發(fā)生超時(shí)等錯(cuò)誤信息了。
private?void?GetTable()????????{
????????????new?EnterpriseServiceClient().Using(enterpriseClient?=>
????????????{
????????????????DataTable?dt?=?enterpriseClient.GetAllForLookUp();
????????????????this.searchPark.Properties.DisplayMember?=?"PARK_NAME";
????????????????this.searchPark.Properties.ValueMember?=?"ID";
????????????????this.searchPark.Properties.DataSource?=?dt;
????????????});?
????????????new?ManufacturerServiceClient().Using(manufacturerClient?=>
????????????{
????????????????ManufacturerInfo[]?manuList?=?manufacturerClient.GetAll();
????????????????this.searchCompany.Properties.DisplayMember?=?"CompanyName";
????????????????this.searchCompany.Properties.ValueMember?=?"ID";
????????????????this.searchCompany.Properties.DataSource?=?manuList;
????????????});?
?? ? ? }?
?
?或者如下例子。
ManufacturerInfo?info?=?null;????????????new?ManufacturerServiceClient().Using(manufacturerClient?=>
????????????????{
????????????????????info?=?manufacturerClient.FindByID(searchCompany.EditValue.ToString());
????????????????});
????????????if?(info?!=?null)
????????????{
????????????????this.txtCompanyAddr.Text?=?info.CompanyAddr;
?? ? ? ? ? ?}?
?
轉(zhuǎn)載于:https://www.cnblogs.com/wuhuacong/archive/2011/10/10/2205180.html
總結(jié)
以上是生活随笔為你收集整理的WCF开发框架形成之旅--WCF应用常见问题处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TCP/IP和UDP的区别
- 下一篇: PS1用法