初学Web Service笔记之动态调用WebService

今天刚学习了下动态调用WebService,顺便写在博客上以方便以后自己用到,也分享给大家。

下面是WebService动态调用示意图

初学Web Service笔记之动态调用WebService_第1张图片

第一步,新建应用程序类库InvokeWebService,再创建静态类WebServiceHelpers,标记为【1】~【11】的解释在代码的后面,代码如下:

代码
   
   
1 public static class WebServiceHelper
2 {
3 /// <summary>
4 /// 动态调用WebService
5 /// </summary>
6 /// <param name="url"> WebService地址 </param>
7 /// <param name="methodname"> 方法名(模块名) </param>
8 /// <param name="args"> 参数列表 </param>
9 /// <returns> object </returns>
10   public static object InvokeWebService( string url, string methodname, object [] args)
11 {
12 return InvokeWebService(url, null , methodname, args);
13 }
14 /// <summary>
15 /// 动态调用WebService
16 /// </summary>
17 /// <param name="url"> WebService地址 </param>
18 /// <param name="classname"> 类名 </param>
19 /// <param name="methodname"> 方法名(模块名) </param>
20 /// <param name="args"> 参数列表 </param>
21 /// <returns> object </returns>
22   public static object InvokeWebService( string url, string classname, string methodname, object [] args)
23 {
24 string @namespace = " ServiceBase.WebService.DynamicWebLoad " ;
25 if (classname == null || classname == "" )
26 {
27 classname = WebServiceHelper.GetClassName(url);
28 }
29 // 获取服务描述语言(WSDL)
30   WebClient wc = new WebClient();
31 Stream stream = wc.OpenRead(url + " ?WSDL " ); // 【1】
32 ServiceDescription sd = ServiceDescription.Read(stream); // 【2】
33 ServiceDescriptionImporter sdi = new ServiceDescriptionImporter(); // 【3】
34 sdi.AddServiceDescription(sd, "" , "" );
35 CodeNamespace cn = new CodeNamespace(@namespace); // 【4】
36 //生成客户端代理类代码
37 CodeCompileUnit ccu = new CodeCompileUnit(); // 【5】
38 ccu.Namespaces.Add(cn);
39 sdi.Import(cn, ccu);
40 CSharpCodeProvider csc = new CSharpCodeProvider(); // 【6】
41 ICodeCompiler icc = csc.CreateCompiler(); // 【7】
42 // 设定编译器的参数
43 CompilerParameters cplist = new CompilerParameters(); // 【8】
44 cplist.GenerateExecutable = false ;
45 cplist.GenerateInMemory = true ;
46 cplist.ReferencedAssemblies.Add( " System.dll " );
47 cplist.ReferencedAssemblies.Add( " System.XML.dll " );
48 cplist.ReferencedAssemblies.Add( " System.Web.Services.dll " );
49 cplist.ReferencedAssemblies.Add( " System.Data.dll " );
50 // 编译代理类
51 CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu); // 【9】
52 if ( true == cr.Errors.HasErrors)
53 {
54 System.Text.StringBuilder sb = new StringBuilder();
55 foreach (CompilerError ce in cr.Errors)
56 {
57 sb.Append(ce.ToString());
58 sb.Append(System.Environment.NewLine);
59 }
60 throw new Exception(sb.ToString());
61 }
62
63 // 生成代理实例,并调用方法
64 System.Reflection.Assembly assembly = cr.CompiledAssembly;
65 Type t = assembly.GetType(@namespace + " . " + classname, true , true );
66 object obj = Activator.CreateInstance(t); // 【10】
67 System.Reflection.MethodInfo mi = t.GetMethod(methodname); // 【11】
68 return mi.Invoke(obj, args);
69
70 }
71
72 private static string GetClassName( string url)
73 {
74 // 假如URL为" http://localhost/InvokeService/Service1.asmx "
75 // 最终的返回值为 Service1
76 string [] parts = url.Split( ' / ' );
77 string [] pps = parts[parts.Length - 1 ].Split( ' . ' );
78 return pps[ 0 ];
79 }
80
81 }

 代码中的注解如下

 【1】如果URL后面不加"?WSDL",运行结果就是在调用Web Service,而不是Web服务描述语言(WSDL),界面如下:

初学Web Service笔记之动态调用WebService_第2张图片

      如果URL后面加上"?WSDL",那返回的才是真正的Web服务描述语言(WSDL),运行结果如下:

初学Web Service笔记之动态调用WebService_第3张图片

 【2】    ServiceDescription类提供一种方法,以创建和格式化用于描述 XML Web services 的有效的 Web 服务描述语言 (WSDL) 文档文件,该文件是完整的,具有适当的命名空间、元素和特性。 无法继承此类。

ServiceDescription.Read 方法 (Stream) 通过直接从 Stream实例加载 XML 来初始化ServiceDescription类的实例。

 【3】    ServiceDescriptionImporter 类 公开一种为 XML Web services 生成客户端代理类的方法。

ServiceDescriptionImporter.AddServiceDescription 方法 将指定的ServiceDescription添加到要导入的ServiceDescriptions值的集合中。

 【4】   CodeNamespace表示命名空间声明。

 【5】   CodeCompileUnit会提供一个CodeDOM程式圆形的容器,CodeCompileUnit含有一个集合,可以储存含有CodeDOM原始程式码原形,专案参考的组件集合以及专案组件属性集合的CodeNamespace物件。

 【6】   CSharpCodeProvider类提供存取C#程式码产生器和程式码编译器的执行个体。

 【7】   取得C#程式码编译器的执行个体

 【8】   创建编译器的参数实例

 【9】   CompilerResults表示从编译器返回的编译结果。使用指定的编译器设定,根据CodeCompileUnit物件之指定阵列所包含的System.CodeDom树状结构,编译一个组件。

 【10】 Activator类包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。无法继承此类Activator.CreateInstance 方法  使用与指定参数匹配程度最高的构造函数创建指定类型的实例。

 【11】 MethodInfo 的实例可以通过调用GetMethods或者Type对象或派生自Type的对象的GetMethod方法来获取,还可以通过调用表示泛型方法定义的 MethodInfo 的MakeGenericMethod方法来获取。

第二步,新建Web Service应用程序,类名为Service1,类里只有一个方法没什么实际用处主要为了练习,代码如下:

代码
   
   
1 /// <summary>
2 /// Service1 的摘要说明
3 /// </summary>
4 [WebService(Namespace = " http://tempuri.org/ " )]
5 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
6 [ToolboxItem( false )]
7 public class Service1 : System.Web.Services.WebService
8 {
9
10 [WebMethod]
11 public string HelloWorld( string Temp1, string Temp2)
12 {
13 return " 参数1: " + Temp1 + "   参数2: " + Temp2;
14 }
15 }

编译成功后发布到本地服务器,在本例子中发布后Web Service路径为“http://localhost/InvokeService/Service1.asmx ”

第三步,创建测试应用程序,在测试应用程序里引入第一步生成的DLL,运行后界面如下:

初学Web Service笔记之动态调用WebService_第4张图片

代码如下:

代码
   
   
1 private void button1_Click( object sender, EventArgs e)
2 {
3 string url = " http://localhost/InvokeService/Service1.asmx " ;
4 string [] args = new string [ 2 ];
5 args[ 0 ] = this .textBox1.Text;
6 args[ 1 ] = this .textBox2.Text;
7
8 object result = InvokeWebService.WebServiceHelper.InvokeWebService(url, " HelloWorld " , args);
9 this .textBox3.Text = result.ToString();
10
11 }

调用Web Service后的运行结果如下:

初学Web Service笔记之动态调用WebService_第5张图片

总结:本例主要用到了以下四个知识点:

 (1)WebService相关知识 ;

Ø (2)代码文档对象模型CodeDom的使用 ;
Ø (3)编程使用C#编译器 ;
Ø (4)反射;

你可能感兴趣的:(Web,service)