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";

 

你可能感兴趣的:(webservice)