using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.IO;
using
System.Configuration;
// 命名空間包含提供用於處理配置數據的編程模型的類型。
using
System.CodeDom;
/*代碼文檔對象模型”, 使用該模型建立的代碼文檔可以被.NET Framework編譯成應用程序集。也就是說,
*你可以使用該模型“發明”一個自己的.net語言,用你的語言編寫程序,再翻譯成codeDom,
* 最後編譯成可以執行的.net應用程序。
*歸根結底在System.CodeDom這個命名空間裏你new來new去只能是得到一些Object而已,
* 而Object是什麼呢,就是內存裏的一點點數據
*/
using
System.CodeDom.Compiler;
/*System.CodeDom.Compiler這個命名空間裏的東西才能把它表現出來。前一個命名空間在於構造,
* 後一個命名空間在於表現。構造就是搭個架子,把裏面的各個部分聚合聚合,連接連接,
* 這個一點點奧祕都沒有,所有也不去深究了
*/
using
System.Net;
//利用System.Net類訪問因特網
using
System.Web.Services;
using
System.Web.Services.Description;
/* 命名空間由使得您可以通過使用 Web 服務描述語言 (WSDL) 來公開描述 XML Web services 的類組成。
* 此命名空間中的每個類都與 WSDL 規範中的某個特定元素相對應,
* 並且類的層次結構與有效的 WSDL 文檔的 XML 結構相對應。
* 有關 WSDL 的更多信息,請參見位於 W3C 網站 (http://www.w3.org/TR/wsdl/) 的規範。
*/
using
Microsoft.CSharp;
//命名空間包含支持使用 C# 語言編譯和生成代碼的類。
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)
//提供向 URI 標識的資源發送數據和從 URI 標識的資源接收數據的公共方法
WebClient wc =
new
WebClient();
Stream stream = wc.OpenRead(url +
"?WSDL"
);
/*下表描述從資源下載數據的 WebClient 方法.相對應的是上載到資源的 WebClient 方法。
* OpenRea 資源以 Stream 的形式返回數據,對應與OpenWrite()
* OpenReadAsync 在不阻止調用線程的情況下,從資源返回數據
* DownloadData從資源下載數據並返回 Byte 數組。
* DownloadDataAsync在不阻止調用線程的情況下,從資源下載數據並返回 Byte 數組。
* DownloadFile從資源將數據下載到本地文件。
* DownloadFileAsync在不阻止調用線程的情況下,將數據從資源下載到本地文件。
* DownloadString從資源下載 String 並返回 String。
* DownloadStringAsync在不阻止調用線程的情況下,從資源下載 String
*/
//ServiceDescription 類與 WSDL 文件的根元素 definitions 相對應。
ServiceDescription sd = ServiceDescription.Read(stream);
//使用 ServiceDescriptionImporter 類可以方便地將 WSDL 說明中包含的信息導入到
//System.CodeDom.CodeCompileUnit 對象
ServiceDescriptionImporter sdi =
new
ServiceDescriptionImporter();
sdi.AddServiceDescription(sd,
""
,
""
);
CodeNamespace cn =
new
CodeNamespace(@
namespace
);
//(二):生成客戶端代理類代碼
/*CodeCompileUnit 包含以下幾個集合:可以存儲包含
* CodeDOM 源代碼圖形的 CodeNamespace 對象的集合、項目引用的程序集的集合,
* 以及項目程序集的屬性集合。
*/
CodeCompileUnit ccu =
new
CodeCompileUnit();
// Add the new namespace to the compile unit.
ccu.Namespaces.Add(cn);
//導入指定的 ServiceDescriptions 值,並將按照 Style 屬性的指定來生成代碼。
// Add the new namespace import for the System namespace
sdi.Import(cn, ccu);
//提供對 C# 代碼生成器和代碼編譯器的實例的訪問。
CSharpCodeProvider csc =
new
CSharpCodeProvider();
/*ICodeCompiler 接口提供用於在運行時使用指定的參數調用編譯的功能,
*以及在編譯之後訪問編譯相關信息的功能,這些信息包括結果代碼和編譯器返回的任何錯誤或警告。
* 每種編譯方法都接受指示編譯器設置的 CompilerParameters 對象,並返回指示編譯結果的 CompilerResults 對象。
*/
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);
//發現方法的屬性 (Attribute) 並提供對方法元數據的訪問。
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];
}
}
}