使用反射動態調用ActiveX控件

使用反射動態調用ActiveX控件ide

袁永福 2018-3-2函數

■■■■問題描述:工具

目前的基於.NET平臺的軟件研發中仍然存在大量的對COM及ActiveX控件的調用。使用C#調用ActiveX控件時通常是使用vs.net工具的添加COM引用時自動生成的互操做性程序集。這種方法操做簡單,能保證必定的性能。但會產生額外的程序文件,不利於應用軟件的簡潔部署。並且當開發環境和運行環境使用的ActiveX控件的版本不一致[袁永福原創]時還容易出錯。性能

筆者長期從事基於.NET平臺的通用產品類軟件研發。[袁永福原創]產品類軟件要求部署簡潔,爲此筆者都會將多個工程編譯生成的多個.NET程序集文件合併成一個.NET程序集文件來作到簡潔部署。ui

實踐中發現自動生成的互操做性程序集沒法合併。另外產品類軟件應該能適應各類複雜的開發和生產環境,甚至ActiveX控件的CLSID 都有可能變化。this

例如,對於COM類庫「HebcaFormSealLib」,VS.NET會自動生成程序集文件「AxInterop.HebcaFormSealLib.dll」、「Interop.HebcaFormSealLib.dll」。這些程序集文件沒法進行程序集合並,並且對於32位或64位的工程項目類型敏感,容易致使錯誤。.net

■■■■技術改進:orm

所以筆者不採用這種自動生成的互操做性程序集。轉而採用自定義的反射來調用ActiveX控件。對象

後期綁定ActiveX 控件主要知識點爲System.Windows.Forms.AxHost類型和Type.InvokeMember方法。blog

AxHost類型是從System.Windows.Forms.Control類型[袁永福原創]派生出來的,專門用於承載ActiveX控件。它是一個抽象類,有一個受保護的構造函數,函數參數是一個guid格式的ActiveX控件的CLSID字符串。還有一個GetOcx內部方法用於建立ActiveX控件的對象實例,它是一個COM對象引用。

建立了這個COM對象引用後就能夠調用Type.InvokerMember方法來動態的調用指定名稱的方法和屬性。

■■■■範例:

筆者最近在使用某電子簽名的ActiveX控件來實現文檔簽名的功能。筆者寫出如下接口代碼

[System.Runtime.InteropServices.ComVisible(false)]
public class DCHebeiCAControl : System.Windows.Forms.AxHost
{
    public DCHebeiCAControl()
        : base("{e4ee564c-0845-4404-91ee-0c206113333f}")
    { }

    public object _ocx = null;
    protected override void AttachInterfaces()
    {
        this._ocx = base.GetOcx();
    }
    private void CheckOCX()
    {
        if (this._ocx == null)
        {
            throw new System.NullReferenceException("_ocx");
        }
    }
    public VersionType GetBaseVersionType()
    {
        this.CheckOCX();
        VersionType result = (VersionType)this._ocx.GetType().InvokeMember(
            "GetBaseVersionType",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }

    public string GetCert(string sealSN)
    {
        this.CheckOCX();
        string result = (string)this._ocx.GetType().InvokeMember(
            "GetCert",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { sealSN });
        return result;
    }

    public string GetClientDetailVersionInfo()
    {
        this.CheckOCX();
        string result = (string)this._ocx.GetType().InvokeMember(
            "GetClientDetailVersionInfo",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }

    public int GetClientVersion()
    {
        this.CheckOCX();
        int result = (int)this._ocx.GetType().InvokeMember(
            "GetClientVersion",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }

    public string GetClientVersionInfo()
    {
        this.CheckOCX();
        string result = (string)this._ocx.GetType().InvokeMember(
            "GetClientVersionInfo",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }

    public object GetConfig(string argName)
    {
        this.CheckOCX();
        object result = (object)this._ocx.GetType().InvokeMember(
            "GetConfig",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { argName });
        return result;
    }
    // ----------- 封裝其餘接口 -----------------------------
}//classDCHebeiCAControl

 

上述代碼中各個功能函數內部代碼結構簡單[袁永福原創],之間有很大的類似性,所以徹底能夠編寫一個代碼生成器來自動生成上述代碼。

完成自定義的控件後,筆者再建立一個WinForm 窗體,在其Load事件中建立控件並添加到窗體上,其代碼以下

private DCHebeiCAControl _Control = null;

private void frmTest_Load(object sender, EventArgs e)
{
    this._Control = new DCHebeiCAControl();
    this._Control.Size = new Size(200, 200);
    this._Control.Location = new Point(0, 0);
    this.Controls.Add(this._Control);
}

 

這樣無需使用自動生成的COM接口程序集便可調用ActiveX控件,大幅提升程序的通用性,並且對於32位和64位的項目類型不敏感。方便部署和更新。

不過這樣因爲採用後期綁定而帶來必定的性能[袁永福原創]問題,所以對於性能敏感而又頻繁調用ActiveX控件的場景下須要謹慎採用這種模式。

 

■■■■小結:

在.net開發中調用舊的ActiveX控件是不少開發場景中不得不作的事情。在本文中,筆者介紹了在C#中調用ActiveX控件的標準模式,並提出了一種[袁永福原創]改良模式來提升程序的通用性。爲操做ActiveX控件的.NET程序開發提供了一種新的技術手段。

相關文章
相關標籤/搜索