asp.net中 正常的調用WebService的方法是添加web引用,但是當一些特殊情況就不是很適用了,如果webService的地址經常變化的話,每次都要重新引用編譯器是件很麻煩的事情。這裡動態引用ws只需要配置一個地址就可以了。
在網上找到了許多的文章具體實現都是差不多的,基本都是同一段代碼。
主要參考一下兩邊文章:
這個是介紹動態調用,主要用的是這哥們的代碼:
http://hddev.blog.51cto.com/3365350/628288
這個是介紹利用反射來擷取返回的數組,雖然有個地方錯了,不過大方向還是對滴:
http://blog.csdn.net/study_live/article/details/5225073
主要用的webservice代理類的代碼,也可以第一篇文章最下面有下載
WebServiceProxy
using System;using System.Web.Services.Description;using System.IO;using System.Net;using System.Xml.Serialization;using System.CodeDom;using System.CodeDom.Compiler;using System.Reflection;public class WebServiceProxy{ private string _className = null; public string WebServiceUrl { get; private set; } private WebServiceProxy(string webServiceUrl) { this.WebServiceUrl = webServiceUrl + "?WSDL"; _className = webServiceUrl.Substring(webServiceUrl.LastIndexOf('/')+1); _className = _className.Substring(0, _className.LastIndexOf('.')); } /// <summary> /// 根據編譯結果產生執行個體並返回 /// </summary> /// <returns></returns> public static object CreateInstance(string webServiceUrl) { WebServiceProxy proxy = new WebServiceProxy(webServiceUrl); CodeCompileUnit unit = proxy.GetServiceCompileUnit(proxy.WebServiceUrl); CompilerResults result = proxy.Compile(unit); Assembly asm = result.CompiledAssembly; object obj = asm.CreateInstance("WebService." + proxy._className); return obj; } /// <summary> /// 獲得CompileUnit /// </summary> /// <param name="webServiceUrl"></param> /// <returns></returns> private CodeCompileUnit GetServiceCompileUnit(string webServiceUrl) { WebClient client = new WebClient(); Stream stream = client.OpenRead(webServiceUrl); //從這個url指向的的是一個xml檔案,裡麵包含了該service的全部資訊。 //進而通過解析xml檔案從而可以產生要編譯的源碼。有興趣的可以看一下xml的內容 ServiceDescription description = ServiceDescription.Read(stream); ServiceDescriptionImporter importer = new ServiceDescriptionImporter();//建立用戶端代理 importer.ProtocolName = "Soap"; //指定訪問協議。 importer.Style = ServiceDescriptionImportStyle.Client; //產生用戶端代理。 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync; importer.AddServiceDescription(description, "", ""); //添加WSDL文檔。 CodeNamespace nmspace = new CodeNamespace(); //命名空間 nmspace.Name = "WebService"; CodeCompileUnit unit = new CodeCompileUnit(); unit.Namespaces.Add(nmspace); ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); return unit; } /// <summary> /// 編譯 /// </summary> /// <param name="unit"></param> /// <returns></returns> private CompilerResults Compile(CodeCompileUnit unit) { CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters compilerParameters = new CompilerParameters(); compilerParameters.GenerateExecutable = false; compilerParameters.GenerateInMemory = true; // cp.OutputAssembly = "D:\\Test.dll";這裡也可以將變異的結果輸出到dll檔案中,從而可以查看編譯的的結果。有興趣的自己看一下。 compilerParameters.ReferencedAssemblies.Add("System.dll"); compilerParameters.ReferencedAssemblies.Add("System.XML.dll"); compilerParameters.ReferencedAssemblies.Add("System.Web.Services.dll"); compilerParameters.ReferencedAssemblies.Add("System.Data.dll"); CompilerResults compilerResults = codeDomProvider.CompileAssemblyFromDom(compilerParameters, unit); if (compilerResults.Errors.HasErrors) { string errors = ""; foreach (var item in compilerResults.Errors) { errors += item.ToString() + Environment.NewLine; } throw new Exception("Compile error:" + errors); } return compilerResults; }}
WebServiceClient.cs
using System;using System.Reflection;/// <summary>/// Summary description for WebServiceClient/// </summary>public class WebServiceClient{ public static string Invoke(string webServiceUrl, string methodName, object[] parameters) { if (string.IsNullOrEmpty(webServiceUrl)) { throw new Exception("WebService url required!"); } if (string.IsNullOrEmpty(methodName)) { throw new Exception("Method name required!"); } object instance = WebServiceProxy.CreateInstance(webServiceUrl); MethodInfo method = instance.GetType().GetMethod(methodName); string result = (string)method.Invoke(instance, parameters); return result; }}
測試方法,分別返回 string,datatable,泛型集合(這裡是其實就是實體類的數組)
string url = "這裡是你的webService地址";//可以放設定檔裡 ////返回字串 //string s = WebServiceClient.Invoke(url, "GetServerName", null); //Response.Write(s); object instance = WebServiceProxy.CreateInstance(url); ////返回datatable //MethodInfo method = instance.GetType().GetMethod("GetSubStationInfo");//方法名稱 //object[] parameters = { "370102002" };//參數 //DataTable dt = (DataTable)method.Invoke(instance, parameters); //返回泛型集合 MethodInfo method = instance.GetType().GetMethod("GetRealData");//方法名稱 // 如果參數傳的是個 dataset , DataSet ds=new DataSet();object[] parameters = {ds}; object[] parameters = { "1510", "5" };//參數 //這裡返回的是一個 實體類的數組 object objArray = method.Invoke(instance, parameters); Type tp = objArray.GetType(); if (tp.IsArray) { object[] dataArray = objArray as object[]; for (int i = 0; i < dataArray.Length; i++) { object s = dataArray[i] as object; Type t = s.GetType(); //利用一下方法擷取到實體類中的屬性的值 //PropertyInfo[] fi = t.GetProperties(); //string str = fi[0].GetValue(s, null).ToString(); string C0001_ITEM_CODE = t.GetProperty("C0001_ITEM_CODE").GetValue(s, null).ToString(); string C0007_PNAME = t.GetProperty("C0007_PNAME").GetValue(s, null).ToString(); //FieldInfo[] fields = t.GetFields();//返回當前type的所有公用欄位 } }