C# 动态调用WebService, 不同结果返回值处理
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的所有公共字段 } }
C# WebService动态调用