等了好久終於等到今天!盼了好久終於把夢實現……哈哈,僅以此歌詞來慶祝我為期3天的wcf學習之路圓滿結束。
今天寫這個文章的目的在於記錄一下我自己在學習WCF的時候碰到的一些問題,俗話說,好記心不如爛筆頭嘛。也為看見我這篇文章的有緣人(正在wcf中探索的人們,提供一點借鑒吧)。
還是老樣子,圖文並茂的文章才是好文章(我自己定義的,勿噴!)。那么接下來我將把我這一路的細節以及碰到的問題和解決方法一一展示出來。
我在學習wcf的時候第一件事就是自己做了個wcf的例子,因為wcf的傳輸協議有很多,比如說http、tcp。我主要講講tcp協議的wcf吧,因為這個確實比較麻煩的一個東西,有時候出現bug也是一些稀奇古怪的exception。廢話不多說直接上圖。
新建一個項目
新建好了的wcf服務庫如下圖
1 namespace WcfServiceLibrary 2 { 3 // 注意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的接口名“IService1”。 4 [ServiceContract] 5 public interface IService1 6 { 7 [OperationContract] 8 string GetData(int value); 9 10 11 } 12 13 14 }
既然wcf叫服務那他總的有服務吧!不然怎么服務於我。別急,上代碼:上面是契約、下面是服務。實際的服務代碼要由契約接口派生實現。
1 namespace WcfServiceLibrary 2 { 3 // 注意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的類名“Service1”。 4 public class Service1 : IService1 5 { 6 public string GetData(int value) 7 { 8 if (value==1) 9 { 10 throw new NotImplementedException(); 11 } 12 return string.Format("You entered: {0}", value); 13 } 14 15 16 } 17 }
以上工作完成后,wcf的創建算是完工了。接下來的重點,是建立wcf的宿主程序。
我就做了和控制台程序作為wcf說的宿主程序!
一般常見的是通過config文件進行配置,以為要深究的話,config文件是在有很東西要講,而我也只是初出茅廬。所以我就一代碼的形式進行配置文件的生成。而且只需要幾個常用的屬性就ok。且看代碼
1.我先實例化綁定形式NetTcpBinding

1 private static NetTcpBinding netTcpBinding = new NetTcpBinding(); 2 public static NetTcpBinding InitNetTcpBinding() 3 { 4 netTcpBinding.Security.Mode = SecurityMode.None; 5 netTcpBinding.ReceiveTimeout = TimeSpan.Parse("00:10:00"); 6 netTcpBinding.MaxBufferPoolSize = 2147483647; // 7 netTcpBinding.MaxBufferSize = 2147483647; 8 //netTcpBinding.MaxConnections = 10; 9 //netTcpBinding.PortSharingEnabled = true; 10 11 netTcpBinding.ReaderQuotas.MaxDepth = 2147483647; 12 netTcpBinding.ReaderQuotas.MaxStringContentLength = 2147483647; 13 netTcpBinding.ReaderQuotas.MaxArrayLength = 2147483647; 14 netTcpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647; 15 netTcpBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647; 16 netTcpBinding.MaxReceivedMessageSize = 2147483647; 17 return netTcpBinding; 18 }
2.我通過反射的形式拿到wcf的契約和服務。

1 public static void LoadAssemBly(string assemblyName) 2 { 3 Assembly assem = Assembly.Load(assemblyName); 4 Dictionary<Type, Type> svTypes = new Dictionary<Type, Type>(); 5 List<TypeInfo> list = assem.DefinedTypes.ToList(); 6 foreach (TypeInfo typeInfo in list) 7 { 8 if (typeInfo.Attributes.ToString().IndexOf("Abstract") >= 0) 9 { 10 TypeInfo tempK = typeInfo; 11 var result = (from t in list where t.Name==(tempK.Name.Substring(1)) select t).ToList(); 12 TypeInfo tempV = result[0]; 13 svTypes.Add(tempK, tempV); 14 } 15 16 } 17 string serviceAddress = string.Format("net.tcp://{0}:{1}", "localhost", "13141"); 18 string endpointAddress = string.Empty; 19 string tName = string.Empty; 20 foreach (var item in svTypes) 21 { 22 tName = item.Key.Name.Substring(1); 23 endpointAddress = serviceAddress +"/"+ tName; 24 25 ServiceHost serviceHost = new ServiceHost(item.Value, new Uri(endpointAddress)); 26 27 //加載元數據節點 28 ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); 29 serviceHost.Description.Behaviors.Add(smb); 30 serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); 31 32 serviceHost.AddServiceEndpoint(item.Key, netTcpBinding, endpointAddress); 33 34 serviceHost.Opened += delegate 35 { 36 msg.AppendLine(string.Format("{0}開始監聽 Uri 為 :{1}/mex", tName, endpointAddress.ToString())); 37 }; 38 serviceHost.Open(); 39 serviceHosts.Add(serviceHost); 40 41 }
這樣我們得宿主程序就完成了。運行一下看看結果
這樣看來是沒問題了,那么們測試一下添加服務引用是否能找到服務。如果找到了就說明確實是沒問題了。
OK,搞定!看似一帆風順。其實這中間我遇到了很多問題,下次再專門寫個博客講解吧
《轉載注明出處!》