using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Web.Services.Description;
using System.Collections.Generic;
//具体步骤:
//1. 从目标 URL 下载 WSDL 数据。
//2. 使用 ServiceDescription 创建和格式化 WSDL 文档文件。
//3. 使用 ServiceDescriptionImporter 创建客户端代理类。
//4. 使用 CodeDom 动态创建客户端代理类程序集。
//5. 利用反射调用相关 WebService 方法。
namespace WebSvrCaller
{
/// <summary>
/// 动态调用WebService
/// </summary>
public class WebServiceCaller
{
/// <summary>
/// WebService类缓存
/// </summary>
static SortedList<string, Type> _typeList = new SortedList<string, Type>();
#region InvokeWebService
private static string GetCacheKey(string url, string className)
{
return url.ToLower() + className;
}
private static Type GetTypeFromCache(string url, string className)
{
string key = GetCacheKey(url, className);
Type result;
if (_typeList.TryGetValue(key, out result))
return result;
else
return null;
}
private static Type GetTypeFromWebService(string url, string className)
{
string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
if (string.IsNullOrEmpty(className))
{
className = GetWsClassName(url);
}
//获取WSDL
WebClient webclient = new WebClient();
Stream stream = webclient.OpenRead(url + "?WSDL");
ServiceDescription servicedes = ServiceDescription.Read(stream);
ServiceDescriptionImporter servicedescriptionimporter = new ServiceDescriptionImporter();
servicedescriptionimporter.AddServiceDescription(servicedes, "", "");
CodeNamespace codenamespace = new CodeNamespace(@namespace);
//生成客户端代理类代码
CodeCompileUnit codecompileunit = new CodeCompileUnit();
codecompileunit.Namespaces.Add(codenamespace);
servicedescriptionimporter.Import(codenamespace, codecompileunit);
CSharpCodeProvider csharpcodeprovider = new CSharpCodeProvider();
ICodeCompiler icodecompiler = csharpcodeprovider.CreateCompiler();
//设定编译参数
CompilerParameters compilerparams = new CompilerParameters();
compilerparams.GenerateExecutable = false;
compilerparams.GenerateInMemory = true;
compilerparams.ReferencedAssemblies.Add("System.dll");
compilerparams.ReferencedAssemblies.Add("System.XML.dll");
compilerparams.ReferencedAssemblies.Add("System.Web.Services.dll");
compilerparams.ReferencedAssemblies.Add("System.Data.dll");
//编译代理类
CompilerResults compilerresult = icodecompiler.CompileAssemblyFromDom(compilerparams, codecompileunit);
if (true == compilerresult.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (System.CodeDom.Compiler.CompilerError ce in compilerresult.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}
//生成代理实例,并调用方法
System.Reflection.Assembly assembly = compilerresult.CompiledAssembly;
Type t = assembly.GetType(@namespace + "." + className, true, true);
return t;
}
//动态调用web服务
public static object InvokeWebService(string url, string methodName, object[] args)
{
return InvokeWebService(url, null, methodName, args);
}
public static object InvokeWebService(string url, string className, string methodName, object[] args)
{
try
{
Type t = GetTypeFromCache(url, className);
if (t == null)
{
t = GetTypeFromWebService(url, className);
//添加到缓冲中
string key = GetCacheKey(url, className);
_typeList.Add(key, t);
}
object obj = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod(methodName);
return mi.Invoke(obj, args);
}
catch (Exception ex)
{
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
}
}
private static string GetWsClassName(string wsUrl)
{
string[] parts = wsUrl.Split('/');
string[] pps = parts[parts.Length - 1].Split('.');
return pps[0];
}
#endregion
}
}
调用:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using Microsoft.CSharp;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Services.Description;
using WebSvrCaller;
namespace test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string url = "http://localhost/WebHoteProvince/Service.asmx";
string[] arg =new string[]{"2e242af2fd174ec18c9e2c94761c8574","admin","admin"};
richTextBox1.AppendText(WebServiceCaller.InvokeWebService(url,"Service", "Login", arg).ToString());
}
}
}