動態調用webservice

 

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];
        }
 
    }
}

 

 

轉載自:http://my.oschina.net/skydog/blog/41227

發佈了2 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章