工具类
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Web.Services.Description;
namespace DynamicWebServiceInvoke
{
public class WebServiceHelper
{
// 静态缓存:URL => 已编译的程序集
private static readonly Dictionary<string, Assembly> AssemblyCache = new Dictionary<string, Assembly>();
/// <summary>
/// 动态调用 WebService(带程序集缓存)
/// </summary>
public static object InvokeWebService(string url, string classname, string methodname, object[] args)
{
Assembly assembly;
// 1️⃣ 如果缓存中已有,直接使用
if (AssemblyCache.ContainsKey(url))
{
assembly = AssemblyCache[url];
}
else
{
// 2️⃣ 动态下载并编译 WSDL
assembly = BuildAssemblyFromWsdl(url);
// 3️⃣ 存入缓存
AssemblyCache[url] = assembly;
}
// 4️⃣ 反射创建对象并调用方法
Type t = assembly.GetType("DynamicWebServiceProxy." + classname, true, true);
object obj = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod(methodname);
return mi.Invoke(obj, args);
}
/// <summary>
/// 从 WSDL 动态生成并编译代理类
/// </summary>
private static Assembly BuildAssemblyFromWsdl(string url)
{
// 下载 WSDL
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?wsdl");
ServiceDescription sd = ServiceDescription.Read(stream);
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
sdi.ProtocolName = "Soap";
sdi.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
// 生成代码
CodeNamespace cn = new CodeNamespace("DynamicWebServiceProxy");
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
// 编译为程序集
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Web.Services.dll");
cp.ReferencedAssemblies.Add("System.Xml.dll");
cp.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults cr = provider.CompileAssemblyFromDom(cp, ccu);
if (cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (CompilerError ce in cr.Errors)
sb.AppendLine(ce.ToString());
throw new Exception("动态编译 WebService 代理类失败:\r\n" + sb.ToString());
}
return cr.CompiledAssembly;
}
}
}
调用示例
using System;
using DynamicWebServiceInvoke;
class Program
{
static void Main()
{
string url = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";
string classname = "WeatherWebService";
string method = "getWeatherbyCityName";
// 参数数组
object[] args = new object[] { "北京" };
// 第一次调用:会下载 WSDL + 编译代理
object result1 = WebServiceHelper.InvokeWebService(url, classname, method, args);
Console.WriteLine("第一次调用结果:");
PrintResult(result1);
Console.WriteLine("\n--------------------\n");
// 第二次调用:直接使用缓存程序集,速度极快
object result2 = WebServiceHelper.InvokeWebService(url, classname, method, args);
Console.WriteLine("第二次调用结果(使用缓存):");
PrintResult(result2);
Console.ReadLine();
}
static void PrintResult(object result)
{
if (result == null)
{
Console.WriteLine("返回为空");
return;
}
if (result is Array)
{
Array arr = (Array)result;
foreach (object o in arr)
{
Console.WriteLine(o);
}
}
else
{
Console.WriteLine(result.ToString());
}
}
}