C#动态调用WebService

 

  用C#调用WebService,一般简单的都是在VS引用里右键添加Web引用,强大的VS就会把所有的代码给你自动生成出来,你要做的就是只要调用就可以了,这里就不详细介绍了。

  先说说我这里的背景,我在做一个软件时,WebService的地址端口等信息不是固定的,会有一个配置文件,用户会自己修改配置文件,这样的话,如果我用自动生成的方式就不可以了,你想啊,我原来WebService的地址是A,你改完之后变成B了,我自动生成的是A的service代码,换成B了还能调用到吗?

  经过各种百度终于找到了动态调用的方法,然后自己改进了一下,如下:

  1 using System;
  2 using System.CodeDom;
  3 using System.CodeDom.Compiler;
  4 using System.Collections.Generic;
  5 using System.IO;
  6 using System.Net;
  7 using System.Web.Services.Description;
  8 using Microsoft.CSharp;
  9 using System.Threading;
 10 
 11 namespace Service
 12 {
 13     public class WebServiceHelp
 14     {
 15         /// <summary>
 16         /// Save assemblys by the specific webservice url
 17         /// </summary>
 18         private static Dictionary<string, System.Reflection.Assembly> Assemblys = new Dictionary<string, System.Reflection.Assembly>();
 19 
 20         /// <summary>
 21         /// Invoke method of web service
 22         /// </summary>
 23         /// <param name="url">service address</param>
 24         /// <param name="className">WebService class name</param>
 25         /// <param name="methodName">Method Name</param>
 26         /// <param name="args">Arguments</param>
 27         /// <returns>Return value</returns>
 28         public static object InvokeWebService(string url, string className, string methodName, params object[] args)
 29         {
 30             string @namespace = "Service";
 31             if (string.IsNullOrEmpty(className))
 32             {
 33                 className = GetWsClassName(url);
 34             }
 35             try
 36             {
 37                 System.Reflection.Assembly assembly = null;
 38                 if (!Assemblys.ContainsKey(url))
 39                 {
 40                     //获取WSDL 
 41                     WebClient wc = new WebClient();
 42                     Stream stream = wc.OpenRead(url + "?WSDL");
 43 
 44                     ServiceDescription sd = ServiceDescription.Read(stream);
 45                     ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
 46                     sdi.AddServiceDescription(sd, "", "");
 47                     CodeNamespace cn = new CodeNamespace(@namespace);
 48                     //生成客户端代理类代码 
 49                     CodeCompileUnit ccu = new CodeCompileUnit();
 50                     ccu.Namespaces.Add(cn);
 51                     sdi.Import(cn, ccu);
 52                     CSharpCodeProvider icc = new CSharpCodeProvider();
 53                     //设定编译参数 
 54                     CompilerParameters cplist = new CompilerParameters();
 55                     cplist.GenerateExecutable = false;
 56                     cplist.GenerateInMemory = true;
 57                     cplist.ReferencedAssemblies.Add("System.dll");
 58                     cplist.ReferencedAssemblies.Add("System.XML.dll");
 59                     cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
 60                     cplist.ReferencedAssemblies.Add("System.Data.dll");
 61                     //编译代理类 
 62                     CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
 63                     if (true == cr.Errors.HasErrors)
 64                     {
 65                         System.Text.StringBuilder sb = new System.Text.StringBuilder();
 66                         foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
 67                         {
 68                             sb.Append(ce.ToString());
 69                             sb.Append(System.Environment.NewLine);
 70                         }
 71                         throw new Exception(sb.ToString());
 72                     }
 73                     //生成代理实例,并调用方法 
 74                     assembly = cr.CompiledAssembly;
 75                     Assemblys[url] = assembly;
 76                 }
 77                 else
 78                 {
 79                     assembly = Assemblys[url];
 80                 }
 81 
 82                 Type t = assembly.GetType(@namespace + "." + className, true, true);
 83                 object obj = Activator.CreateInstance(t);
 84                 System.Reflection.MethodInfo mi = t.GetMethod(methodName);
 85                 return mi.Invoke(obj, args);
 86             }
 87             catch (ThreadAbortException tae)
 88             {
 89                 //Logger.Warn(tae.ToString());
 90                 return null;
 91             }
 92             catch (Exception ex)
 93             {
 94                 //Logger.Error(ex.ToString());
 95                 throw new Exception(ex.Message);
 96             }
 97         }
 98 
 99         private static string GetWsClassName(string wsUrl)
100         {
101             string[] parts = wsUrl.Split('/');
102             string[] pps = parts[parts.Length - 1].Split('.');
103             return pps[0];
104         }
105     }
106 }

这里说明一下,开头的Assemblys是用来存放动态编译的Assembly信息,不然的话,每次调用Service方法都要重新生成一边,那是相当的慢啊!

在调用的时候只要传入相应的信息就可以了,调用时:

1 public string GetPathByVMID(string vmId)
2         {
3             return WebServiceHelp.InvokeWebService(ConfigConstant.ServiceAdress, "VMServiceService", "getPathByVmID", vmId) as string;
4         }

 ServiceAdress的格式"http://127.0.0.1:8080/services/VMService";

 

posted @ 2013-08-01 13:49  老笨孩  阅读(380)  评论(0编辑  收藏  举报