在做多個系統整合的時候,由於各系統廠商採用不同的架構,在專案實施前期,各業務對業務理解不夠深入,系統介面可能會有較多變化,
在此背景下,動態呼叫webserivce就變得靈活了,降低了系統整合的耦合度。
下面介紹動態呼叫的具體步驟:
具體步驟:
1. 從目標 URL 下載 WSDL 資料。
2. 使用 ServiceDescription 建立和格式化 WSDL 文件檔案。
3. 使用 ServiceDescriptionImporter 建立客戶端代理類。
4. 使用 CodeDom 動態建立客戶端代理類程式集。
5. 利用反射呼叫相關 WebService 方法。
其實與手工建立新增引用步驟一樣,只是在這裡把手動變成了自動而已,動態生成代理類,利用反射動態呼叫了方法。
下面看程式碼:程式碼也是摘自博友的,只是作了一些小的修改,
1 /// < summary> 2 /// 動態呼叫web服務 3 /// < /summary> 4 /// < param name="url">WSDL服務地址< /param> 5 /// < param name="classname">類名< /param> 6 /// < param name="methodname">方法名< /param> 7 /// < param name="args">引數< /param> 8 /// < returns>< /returns> 9 public object InvokeWebService(string url, string classname, string methodname, object[] args) 10 { 11 string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling"; 12 if ((classname == null) || (classname == "")) 13 { 14 classname = CommonServiceHelper.GetWsClassName(url); 15 } 16 try 17 { 18 //獲取WSDL 19 WebClient wc = new WebClient(); 20 Stream stream = wc.OpenRead(url + "?WSDL"); 21 ServiceDescription sd = ServiceDescription.Read(stream); 22 ServiceDescriptionImporter sdi = new ServiceDescriptionImporter(); 23 sdi.AddServiceDescription(sd, "", ""); 24 CodeNamespace cn = new CodeNamespace(@namespace); 25 //生成客戶端代理類程式碼 26 CodeCompileUnit ccu = new CodeCompileUnit(); 27 ccu.Namespaces.Add(cn); 28 sdi.Import(cn, ccu); 29 CSharpCodeProvider icc = new CSharpCodeProvider(); 30 //設定編譯引數 31 CompilerParameters cplist = new CompilerParameters(); 32 cplist.GenerateExecutable = false; 33 cplist.GenerateInMemory = true; 34 cplist.ReferencedAssemblies.Add("System.dll"); 35 cplist.ReferencedAssemblies.Add("System.XML.dll"); 36 cplist.ReferencedAssemblies.Add("System.Web.Services.dll"); 37 cplist.ReferencedAssemblies.Add("System.Data.dll"); 38 //編譯代理類 39 CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu); 40 if (true == cr.Errors.HasErrors) 41 { 42 System.Text.StringBuilder sb = new System.Text.StringBuilder(); 43 foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors) 44 { 45 sb.Append(ce.ToString()); 46 sb.Append(System.Environment.NewLine); 47 } 48 throw new Exception(sb.ToString()); 49 } 50 //生成代理例項,並呼叫方法 51 System.Reflection.Assembly assembly = cr.CompiledAssembly; 52 Type t = assembly.GetType(@namespace + "." + classname, true, true); 53 object obj = Activator.CreateInstance(t); 54 System.Reflection.MethodInfo mi = t.GetMethod(methodname); 55 return mi.Invoke(obj, args); 56 /* 57 * PropertyInfo propertyInfo = type.GetProperty(propertyname); 58 * return propertyInfo.GetValue(obj, null); 59 * */ 60 } 61 catch (Exception ex) 62 { 63 throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace)); 64 } 65 } 66 private static string GetWsClassName(string wsUrl) 67 { 68 string[] parts = wsUrl.Split('/'); 69 string[] pps = parts[parts.Length - 1].Split('.'); 70 return pps[0]; 71 }
單元測試程式碼:
1 /// <summary> 2 ///InvokeWebService 的測試 3 ///</summary> 4 [TestMethod()] 5 public void InvokeWebServiceTest() 6 { 7 CommonServiceHelper target = new CommonServiceHelper(); // TODO: 初始化為適當的值 8 string url = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx"; // TODO: 初始化為適當的值 9 string classname = string.Empty; // TODO: 初始化為適當的值 10 string methodname = "getWeather"; // TODO: 初始化為適當的值 11 string[] a = new string[2] { "bj","" }; 12 object[] args = a; // TODO: 初始化為適當的值 13 object expected = null; // TODO: 初始化為適當的值 14 object actual; 15 actual = target.InvokeWebService(url, classname, methodname, args); 16 Assert.AreEqual(expected, actual); 17 Assert.Inconclusive("驗證此測試方法的正確性。"); 18 }