天天看點

Web Service學習筆記:動态調用WebService

多數時候我們通過 "添加 Web 引用..." 建立用戶端代理類的方式調用WebService,但在某些情況下我們可能需要在程式運作期間動态調用一個未知的服務。在 .NET Framework 的 System.Web.Services.Description 命名空間中有我們需要的東西。

具體步驟:

1. 從目标 URL 下載下傳 WSDL 資料。

2. 使用 ServiceDescription 建立和格式化 WSDL 文檔檔案。

3. 使用 ServiceDescriptionImporter 建立用戶端代理類。

4. 使用 CodeDom 動态建立用戶端代理類程式集。

5. 利用反射調用相關 WebService 方法。

OK,看看具體的例子。

Web Service學習筆記:動态調用WebService

HelloWorld.asmx [WebService(Namespace = "http://www.rainsts.net/", Description="我的Web服務")]

Web Service學習筆記:動态調用WebService

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

public class WebService : System.Web.Services.WebService 

Web Service學習筆記:動态調用WebService

{

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

public WebService () 

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

}

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

  [WebMethod]

Web Service學習筆記:動态調用WebService

  public string HelloWorld()

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

    return "Hello Wolrd!";

Web Service學習筆記:動态調用WebService

  }

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

1. 動态調用 WebService

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

用戶端動态調用代碼

Web Service學習筆記:動态調用WebService

using System.IO;

Web Service學習筆記:動态調用WebService

using System.Net;

Web Service學習筆記:動态調用WebService

using System.Reflection;

Web Service學習筆記:動态調用WebService

using System.CodeDom;

Web Service學習筆記:動态調用WebService

using System.CodeDom.Compiler;

Web Service學習筆記:動态調用WebService

using System.Web.Services;

Web Service學習筆記:動态調用WebService

using System.Web.Services.Description;

Web Service學習筆記:動态調用WebService

using System.Web.Services.Protocols;

Web Service學習筆記:動态調用WebService

using System.Xml.Serialization;

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

// 1. 使用 WebClient 下載下傳 WSDL 資訊。

Web Service學習筆記:動态調用WebService

WebClient web = new WebClient();

Web Service學習筆記:動态調用WebService

Stream stream = web.OpenRead("http://localhost:60436/Learn.WEB/WebService.asmx?WSDL");

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

// 2. 建立和格式化 WSDL 文檔。

Web Service學習筆記:動态調用WebService

ServiceDescription description = ServiceDescription.Read(stream);

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

// 3. 建立用戶端代理代理類。

Web Service學習筆記:動态調用WebService

ServiceDescriptionImporter importer = new ServiceDescriptionImporter();

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

importer.ProtocolName = "Soap"; // 指定通路協定。

Web Service學習筆記:動态調用WebService

importer.Style = ServiceDescriptionImportStyle.Client; // 生成用戶端代理。

Web Service學習筆記:動态調用WebService

importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync; 

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

importer.AddServiceDescription(description, null, null); // 添加 WSDL 文檔。

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

// 4. 使用 CodeDom 編譯用戶端代理類。

Web Service學習筆記:動态調用WebService

CodeNamespace nmspace = new CodeNamespace(); // 為代理類添加命名空間,預設為全局空間。

Web Service學習筆記:動态調用WebService

CodeCompileUnit unit = new CodeCompileUnit();

Web Service學習筆記:動态調用WebService

unit.Namespaces.Add(nmspace);

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); 

Web Service學習筆記:動态調用WebService

CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

CompilerParameters parameter = new CompilerParameters();

Web Service學習筆記:動态調用WebService

parameter.GenerateExecutable = false;

Web Service學習筆記:動态調用WebService

parameter.GenerateInMemory = true;

Web Service學習筆記:動态調用WebService

parameter.ReferencedAssemblies.Add("System.dll");

Web Service學習筆記:動态調用WebService

parameter.ReferencedAssemblies.Add("System.XML.dll");

Web Service學習筆記:動态調用WebService

parameter.ReferencedAssemblies.Add("System.Web.Services.dll");

Web Service學習筆記:動态調用WebService

parameter.ReferencedAssemblies.Add("System.Data.dll");

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

// 5. 使用 Reflection 調用 WebService。

Web Service學習筆記:動态調用WebService

if (!result.Errors.HasErrors)

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

  Assembly asm = result.CompiledAssembly;

Web Service學習筆記:動态調用WebService

  Type t = asm.GetType("WebService"); // 如果在前面為代理類添加了命名空間,此處需要将命名空間添加到類型前面。

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

  object o = Activator.CreateInstance(t);

Web Service學習筆記:動态調用WebService

  MethodInfo method = t.GetMethod("HelloWorld");

Web Service學習筆記:動态調用WebService

  Console.WriteLine(method.Invoke(o, null));

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

2. 生成用戶端代理程式集檔案

上面的代碼通過在記憶體中建立動态程式集的方式完成了動态調用過程。如果我們希望将用戶端代理類生成程式集檔案儲存到硬碟,則可以進行如下修改。生成程式集檔案後,我們可以通過 Assembly.LoadFrom() 載入并進行反射調用。對于需要多次調用的系統,要比每次生成動态程式集效率高出很多。

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

parameter.OutputAssembly = "test.dll"; // 可以指定你所需的任何檔案名。

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

if (result.Errors.HasErrors)

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

  // 顯示編譯錯誤資訊

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

調用程式集檔案示範

Web Service學習筆記:動态調用WebService

Assembly asm = Assembly.LoadFrom("test.dll");

Web Service學習筆記:動态調用WebService

Type t = asm.GetType("WebService"); 

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

object o = Activator.CreateInstance(t);

Web Service學習筆記:動态調用WebService

MethodInfo method = t.GetMethod("HelloWorld");

Web Service學習筆記:動态調用WebService

Console.WriteLine(method.Invoke(o, null));

Web Service學習筆記:動态調用WebService

3. 擷取用戶端代理類源代碼

還有一種情形,就是我們需要獲得用戶端代理類的 C# 源代碼。

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

// 5. 儲存源代碼到檔案。當然,你也可以直接儲存到記憶體字元串中。

Web Service學習筆記:動态調用WebService

TextWriter writer = File.CreateText("test.cs"); // 指定你所需的源代碼檔案名。

Web Service學習筆記:動态調用WebService

provider.GenerateCodeFromCompileUnit(unit, writer, null);

Web Service學習筆記:動态調用WebService

writer.Flush();

Web Service學習筆記:動态調用WebService

writer.Close();

Web Service學習筆記:動态調用WebService
Web Service學習筆記:動态調用WebService

如果你調用時觸發 "WebException: 請求因 HTTP 狀态 415 失敗: Unsupported Media Type。" 這樣的異常,那麼恭喜你和我一樣郁悶,趕緊把伺服器端的 WSE 關掉吧。在必須使用 WSE 的情況下,需要對用戶端進行調整.