用C#通過反射實現動態調用WebService 告別Web引用


我們都知道,調用WebService可以在工程中對WebService地址進行WEB引用,但是這確實很不方便。我想能夠利用配置文件靈活調用WebService。如何實現呢?

用C#通過反射實現動態調用WebService

上代碼,先試再說:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web.Services.Description;
using System.CodeDom;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace TestCommon
{
    public class Webservice
    {
        /// <summary>
        /// 實例化WebServices
        /// </summary>
        /// <param name="url">WebServices地址</param>
        /// <param name="methodname">調用的方法</param>
        /// <param name="args">把webservices里需要的參數按順序放到這個object[]里</param>
        public static object InvokeWebService(string url, string methodname, object[] args)
        {

            //這里的namespace是需引用的webservices的命名空間,我沒有改過,也可以使用。也可以加一個參數從外面傳進來。
            string @namespace = "client";
            try
            {
                //獲取WSDL
                WebClient wc = new WebClient();
                Stream stream = wc.OpenRead(url + "?WSDL");
                ServiceDescription sd = ServiceDescription.Read(stream);
                string classname = sd.Services[0].Name;
                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
                sdi.AddServiceDescription(sd, "", "");
                CodeNamespace cn = new CodeNamespace(@namespace);

                //生成客戶端代理類代碼
                CodeCompileUnit ccu = new CodeCompileUnit();
                ccu.Namespaces.Add(cn);
                sdi.Import(cn, ccu);
                CSharpCodeProvider csc = new CSharpCodeProvider();
                //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 = csc.CompileAssemblyFromDom(cplist, ccu);
                if (true == cr.Errors.HasErrors)
                {
                    System.Text.StringBuilder sb = new System.Text.StringBuilder();
                    foreach (System.CodeDom.Compiler.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);
                System.Reflection.MethodInfo mi = t.GetMethod(methodname);

                return mi.Invoke(obj, args);
            }
            catch
            {
                return null;
            }
        }
    }
}

注意:上述代碼需要引用如下四個名稱空間:
using System.Web.Services.Description;  //WS的描述
//以下幾個用於根據描述動態生成代碼並動態編譯獲取程序集
using System.CodeDom;  
using Microsoft.CSharp;
using System.CodeDom.Compiler;

如果你看到這段文字,說明您正使用RSS閱讀或轉自《一棵樹-博客園》,原文地址:http://www.cnblogs.com/atree/p/WebService_dynamic.html

代碼相對簡單,為什么可以如此調用呢?動態編譯后用反射來讀取並執行。也許了解反射及如何反射對你會有幫助。

反射提供了封裝程序集、模塊和類型的對象(Type 類型)。可以使用反射動態創建類型的實例,將類型綁定到現有對象,或從現有對象獲取類型並調用其方法或訪問其字段和屬性。詳細請查看:https://msdn.microsoft.com/zh-cn/library/ms173183(VS.80).aspx

為什么WebServices可以通過反射實現?

WebService在傳輸過程中是通過WSDL來進行描述的(使用SOAP協議)。因此,我們需要獲取WebService的WSDL描述,並通過該描述來動態生成程序集。然后通過反射來獲取新生成的程序集,並調用其方法!

以下是MSDN對其的描述:

XML Web services 的接口通常由 Web 服務描述語言 (WSDL) 文件來說明。例如,若要獲取有關使用 http://localhost/service.asmx 處公開的 ASP.NET 的 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 的功能而不進行實現。然后,可以通過編寫從這些抽象類繼承的類來對其進行實現,並實現相關的方法。

了解更多關於WebServices的知識:

C#調用WebService實例和開發

Web Service 的工作原理

MSDN:https://msdn.microsoft.com/zh-cn/library/system.web.services.webservice(VS.80).aspx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM