- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- using System.Configuration;
- using System.CodeDom;
- using System.CodeDom.Compiler;
- using System.Net;
- using System.Web.Services;
- using System.Web.Services.Description;
- using Microsoft.CSharp;
- namespace InvokeWebService
- {
- public static class WebServiceHelper
- {
- /// <summary>
- /// 动态调用WebService
- /// </summary>
- /// <param name="url">WebService地址</param>
- /// <param name="methodname">方法名(模块名)</param>
- /// <param name="args">参数列表</param>
- /// <returns>object</returns>
- public static object InvokeWebService(string url, string methodname, object[] args)
- {
- return InvokeWebService(url, null, methodname, args);
- }
- /// <summary>
- /// 动态调用WebService
- /// </summary>
- /// <param name="url">WebService地址</param>
- /// <param name="classname">类名</param>
- /// <param name="methodname">方法名(模块名)</param>
- /// <param name="args">参数列表</param>
- /// <returns>object</returns>
- public static object InvokeWebService(string url, string classname, string methodname, object[] args)
- {
- string @namespace = "ServiceBase.WebService.DynamicWebLoad";
- if (classname == null || classname == "")
- {
- classname = WebServiceHelper.GetClassName(url);
- }
- //获取服务描述语言(WSDL)
- WebClient wc = new WebClient();
- Stream stream = wc.OpenRead(url + "?WSDL");
- ServiceDescription sd = ServiceDescription.Read(stream);
- ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
- sdi.AddServiceDescription(sd, "", "");
- CodeNamespace cn = new CodeNamespace(@namespace);
- //生成客户端代理类代码
- CodeCompileUnit ccu = new CodeCompileUnit();
- ccu.Namespaces.Add(cn);
- sdi.Import(cn, ccu);
- CSharpCodeProvider csc = new CSharpCodeProvider();
- ICodeCompiler icc = csc.CreateCompiler();
- //设定编译器的参数
- CompilerParameters cplist = new CompilerParameters();
- cplist.GenerateExecutable = false;
- cplist.GenerateInMemory = true;
- cplist.ReferencedAssemblies.Add("System.dll");
- cplist.ReferencedAssemblies.Add("System.XML.dll");
- cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
- cplist.ReferencedAssemblies.Add("System.Data.dll");
- //编译代理类
- CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
- if (true == cr.Errors.HasErrors)
- {
- System.Text.StringBuilder sb = new StringBuilder();
- foreach (CompilerError ce in cr.Errors)
- {
- sb.Append(ce.ToString());
- sb.Append(System.Environment.NewLine);
- }
- throw new Exception(sb.ToString());
- }
- //生成代理实例,并调用方法
- System.Reflection.Assembly assembly = cr.CompiledAssembly;
- Type t = assembly.GetType(@namespace + "." + classname, true, true);
- object obj = Activator.CreateInstance(t);
- System.Reflection.MethodInfo mi = t.GetMethod(methodname);
- return mi.Invoke(obj, args);
- }
- private static string GetClassName(string url)
- {
- string[] parts = url.Split('/');
- string[] pps = parts[parts.Length - 1].Split('.');
- return pps[0];
- }
- }
- }
调用示例
上面的注释已经很好的说明了各代码段的功能,下面给个例子看看,这个例子是通过访问http://www.webservicex.net/globalweather.asmx 服务来获取各大城市的天气状况。
string[] args = new string[2] ;
args[0] = this.textBox_CityName.Text ;
args[1] = "China" ;
object result = WebServiceHelper.InvokeWebService(url ,"GetWeather" ,args) ;
this.label_Result.Text = result.ToString() ;
上述的例子中,调用web服务使用了两个参数,第一个是城市的名字,第二个是国家的名字,Web服务返回的是XML文档,可以从其中解析出温度、风力等天气情况。
最后说一下,C#虽然仍属于静态语言之列,但是其动态能力也是很强大的,不信,你可以看看Spring.net的AOP实现,这种“无侵入”的AOP实现比通常的.NET声明式AOP实现(一般是通过AOP Attribute)要漂亮的多。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string url = "http://localhost/InvokeService/Service1.asmx";
string[] args = new string[2];
args[0] = this.textBox1.Text;
args[1] = this.textBox2.Text;
object result = InvokeWebService.WebServiceHelper.InvokeWebService(url, "HelloWorld", args);
this.textBox3.Text = result.ToString();
}
}
}
方法二:
- 我也写了一个,可以调用, 没发现问题, 如下:
- const string DefaultUrl = "http://192.168.60.27/ServiceDS/Service.asmx?wsdl";
- static Program instance = new Program();
- static void Main(string[] args)
- {
- instance.InvokeMethod();
- Console.ReadLine();
- }
- void InvokeMethod()
- {
- Assembly proxyAssembly = CreateWSProxy(DefaultUrl);
- Type proxyType = proxyAssembly.GetType("WebServiceProxy.Service");
- MethodInfo mi = proxyType.GetMethod("xxxMethod");
- PropertyInfo pi = proxyType.GetProperty("Credentials");
- object proxy = Activator.CreateInstance(proxyType);
- pi.SetValue(proxy, CredentialCache.DefaultCredentials, new object[0]);
- Console.WriteLine(mi.Invoke(proxy, new object[] { "xxx" }).ToString());
- }
- Assembly CreateWSProxy(string url)
- {
- if (String.IsNullOrEmpty(url))
- return null;
- ServiceDescription wsdl = GetWsdl(url);
- CodeNamespace cns = new CodeNamespace("WebServiceProxy");
- ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
- sdi.AddServiceDescription(wsdl, null, null);
- sdi.ProtocolName = "Soap";
- sdi.Import(cns, null);
- CSharpCodeProvider cp = new CSharpCodeProvider();
- StringBuilder sb = new StringBuilder();
- StringWriter sw = new StringWriter(sb);
- cp.GenerateCodeFromNamespace(cns, sw, null);
- string src = sb.ToString();
- sw.Close();
- Console.WriteLine(src);
- CompilerParameters cmp = new CompilerParameters();
- cmp.ReferencedAssemblies.Add("System.dll");
- cmp.ReferencedAssemblies.Add("System.Xml.dll");
- cmp.ReferencedAssemblies.Add("System.Web.Services.dll");
- cmp.GenerateExecutable = false;
- cmp.GenerateInMemory = true;
- cmp.IncludeDebugInformation = false;
- CompilerResults cr = cp.CompileAssemblyFromSource(cmp, src);
- if (cr.Errors.Count > 0)
- throw new Exception(string.Format("Build failed: {0} errors",
- cr.Errors.Count));
- return cr.CompiledAssembly;
- }
- ServiceDescription GetWsdl(string url)
- {
- WebRequest wreq = WebRequest.Create(url);
- wreq.Credentials = CredentialCache.DefaultCredentials;
- WebResponse resp = wreq.GetResponse();
- Stream stream = resp.GetResponseStream();
- StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8);
- string desc = sr.ReadToEnd();
- XmlTextReader xtr = new XmlTextReader(new StringReader(desc));
- ServiceDescription wsdl = ServiceDescription.Read(xtr);
- xtr.Close();
- sr.Close();
- stream.Close();
- resp.Close();
- return wsdl;
- }