当前位置:文档之家› C# .NET 动态调用webservice的三种方式

C# .NET 动态调用webservice的三种方式

动态调用webservice的三种方式多数时候我们通过"添加Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我们可能需要在程序运行期间动态调用一个未知的服务。

在.NET Framework 的System.Web.Services.Description 命名空间中有我们需要的东西。

具体步骤:1. 从目标URL 下载WSDL 数据。

2. 使用ServiceDescription 创建和格式化WSDL 文档文件。

3. 使用ServiceDescriptionImporter 创建客户端代理类。

4. 使用CodeDom 动态创建客户端代理类程序集。

5. 利用反射调用相关WebService 方法。

上述步骤需要引用如下四个名称空间:using System.Web.Services.Description; //WS的描述//以下几个用于根据描述动态生成代码并动态编译获取程序集using System.CodeDom;using Microsoft.CSharp;using piler;上述几个名称空间中包括如下几个重要的类:using System.Web.Services.Description下:ServiceDescription //WS描述ServiceDescriptionImporter //通过描述生成客户端代理类,特别注意其中的Style以下是MSDN对其的描述:XML Web services 的接口通常由Web 服务描述语言(WSDL) 文件来说明。

例如,若要获取有关使用http://localhost/service.asmx 处公开的 的Web 服务的WSDL 说明,只需导航到http://localhost/service.asmx?WSDL。

使用ServiceDescriptionImporter 类可以方便地将WSDL 说明中包含的信息导入到System.CodeDom.CodeCompileUnit 对象。

通过调整Style 参数的值,可以指示ServiceDescriptionImporter 实例生成客户端代理类(通过透明调用该类可提供Web 服务的功能)或生成抽象类(该类封装Web 服务的功能而不实现该功能)。

如果将Style 属性设置为Client,则ServiceDescriptionImporter 生成客户端代理类,通过调用这些类来提供说明的Web 服务的功能。

如果将Style 属性设置为Server,则ServiceDescriptionImporter 实例生成抽象类,这些类表示所说明的XML Web services 的功能而不进行实现。

然后,可以通过编写从这些抽象类继承的类来对其进行实现,并实现相关的方法。

using System.CodeDom下:CodedomUnit //它用于设定动态代码的名称空间,类名等,可以通过ServiceDescriptionImporter.Import()方法将WS的描述代码写入该类,以作动态编译用using piler下:CodedomProvider //用于创建和检索代码生成器和代码编译器的实例,我们主要用到其实现子类CShareCodeProvider可以直接用CShareCodeProvider provider=new CShareCodeProvider()来生成,或者用CodedomProvider.CreateProvider("CSharp")来生成ICodeCompiler //用于编译基于System.CodeDom 的源代码表示形式。

它通过CodedomProvider的CreateCompiler()方法来CompilerResults //表示从编译器返回的编译结果。

它由ICodeCompiler根据指定的编译器设置从指定的CodeCompileUnit 所包含的System.CodeDom 树中编译程序集并返回。

CompiledAssembly 属性指示编译的程序集。

了解如上信息后,就可动态调用WS了。

OK,看看具体的例子。

我们要调用的目标WebService,其URL 是http://localhost:60436/Learn.WEB/WebService.asmxHelloWorld.asmx[WebService(Namespace = "/", Description="我的Web服务")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]public class WebService : System.Web.Services.WebService {public WebService () {}[WebMethod]public string HelloWorld(){return "Hello Wolrd!";}}1. 动态调用WebService客户端动态调用代码using System.IO;using ;using System.Reflection;using System.CodeDom;using piler;using System.Web.Services;using System.Web.Services.Description;using System.Web.Services.Protocols;using System.Xml.Serialization;// 1. 使用WebClient 下载WSDL 信息。

WebClient web = new WebClient();Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");// 2. 创建和格式化WSDL 文档。

ServiceDescription description = ServiceDescription.Read(stream);// 3. 创建客户端代理代理类。

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();importer.ProtocolName = "Soap"; // 指定访问协议。

importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。

importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;importer.AddServiceDescription(description, null, null); // 添加WSDL 文档。

// 4. 使用CodeDom 编译客户端代理类。

CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。

CodeCompileUnit unit = new CodeCompileUnit();spaces.Add(nmspace);ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");CompilerParameters parameter = new CompilerParameters();parameter.GenerateExecutable = false;parameter.GenerateInMemory = true;parameter.ReferencedAssemblies.Add("System.dll");parameter.ReferencedAssemblies.Add("System.XML.dll");parameter.ReferencedAssemblies.Add("System.Web.Services.dll");parameter.ReferencedAssemblies.Add("System.Data.dll");CompilerResults result = pileAssemblyFromDom(parameter, unit);// 5. 使用Reflection 调用WebService。

if (!result.Errors.HasErrors){Assembly asm = piledAssembly;Type t = asm.GetType("WebService"); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。

object o = Activator.CreateInstance(t);MethodInfo method = t.GetMethod("HelloWorld");Console.WriteLine(method.Invoke(o, null));}2. 生成客户端代理程序集文件上面的代码通过在内存中创建动态程序集的方式完成了动态调用过程。

如果我们希望将客户端代理类生成程序集文件保存到硬盘,则可以进行如下修改。

生成程序集文件后,我们可以通过Assembly.LoadFrom() 载入并进行反射调用。

对于需要多次调用的系统,要比每次生成动态程序集效率高出很多。

using System.IO;using ;using System.CodeDom;using piler;using System.Web.Services;using System.Web.Services.Description;using System.Web.Services.Protocols;using System.Xml.Serialization;// 1. 使用WebClient 下载WSDL 信息。

相关主题