首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 實現 VB 風格 CreateObject 晚期繫結呼叫 COM 物件

     編輯:關於C#

VB6 時代的 CreateObject("ProgID") 讓開發者能輕鬆晚期繫結呼叫 COM 元件。C# 雖可透過 Microsoft.VisualBasic.Interaction.CreateObject 達到同樣效果,但回傳 object 導致無法直接存取成員。本文介紹純 C# 方式:使用 System.Activator.CreateInstance 搭配反射 InvokeMember 完美複製 VB 的晚期繫結行為。

核心類別與方法對照

VB6C# 等效說明
CreateObject("ProgID")Activator.CreateInstance(Type.GetTypeFromProgID("ProgID"))依 ProgID 建立 COM 物件執行個體
obj.Method(args)type.InvokeMember("Method", BindingFlags.InvokeMethod, null, obj, args)呼叫方法
val = obj.Function(args)val = type.InvokeMember("Function", BindingFlags.InvokeMethod, null, obj, args)呼叫有回傳值的函式
val = obj.Propertyval = type.InvokeMember("Property", BindingFlags.GetProperty, null, obj, null)取得屬性值
obj.Property = valtype.InvokeMember("Property", BindingFlags.SetProperty, null, obj, new object[]{val})設定屬性值

完整程式碼範例:通用晚期繫結包裝

using System;
using System.Reflection;

public class LateBindingHelper
{
    /// 
    /// 建立 COM 物件並回傳 (Type, Instance) 配對,方便後續 InvokeMember
    /// 
    public static (Type ComType, object Instance) CreateComObject(string progId)
    {
        Type t = Type.GetTypeFromProgID(progId, throwOnError: true);
        object inst = Activator.CreateInstance(t);
        return (t, inst);
    }

    /// 
    /// 呼叫方法 (無回傳值)
    /// 
    public static void InvokeMethod(Type t, object inst, string name, params object[] args)
        => t.InvokeMember(name, BindingFlags.InvokeMethod, null, inst, args);

    /// 
    /// 呼叫函式/方法 (有回傳值)
    /// 
    public static T InvokeFunction<T>(Type t, object inst, string name, params object[] args)
        => (T)t.InvokeMember(name, BindingFlags.InvokeMethod, null, inst, args);

    /// 
    /// 取得屬性值
    /// 
    public static T GetProperty<T>(Type t, object inst, string name)
        => (T)t.InvokeMember(name, BindingFlags.GetProperty, null, inst, null);

    /// 
    /// 設定屬性值
    /// 
    public static void SetProperty(Type t, object inst, string name, object value)
        => t.InvokeMember(name, BindingFlags.SetProperty, null, inst, new object[] { value });
}

實戰範例:自動化 Word 產生文件

public void AutomateWord()
{
    var (wordType, wordApp) = LateBindingHelper.CreateComObject("Word.Application");
    
    // 設定可見
    LateBindingHelper.SetProperty(wordType, wordApp, "Visible", true);
    
    // 取得 Documents 集合
    object docs = LateBindingHelper.GetProperty(wordType, wordApp, "Documents");
    Type docsType = docs.GetType();
    
    // 新增文件
    object doc = LateBindingHelper.InvokeFunction(docsType, docs, "Add");
    
    // 此處可繼續操作 doc 物件...
    // 記得最後釋放:Marshal.ReleaseComObject(wordApp) 等
}


關鍵注意事項

  • 效能:晚期繫結每次呼叫皆經反射,效能較早期繫結 (加入參考、介面強型別) 低,高頻呼叫建議改用早期繫結。
  • 例外處理:InvokeMember 可能拋出 TargetInvocationException,真實錯誤在 InnerException 中。
  • 資源釋放:COM 物件需呼叫 System.Runtime.InteropServices.Marshal.ReleaseComObject 釋放,並建議搭配 GC.Collect()、GC.WaitForPendingFinalizers()。
  • ProgID 取得:可在登錄表 HKEY_CLASSES_ROOT 搜尋,或參考元件的類別庫 (TLB) 文件。

早期繫結 vs 晚期繫結快速比較

特性早期繫結晚期繫結
開發體驗IntelliSense、編譯期型別檢查純字串、執行期才發現錯誤
部署相依性需目標機安裝相同版本 COM 元件僅需 ProgID 存在,版本彈性較大
效能直接虛擬函式呼叫,極快反射呼叫,有額外負擔
適用場景核心高頻自動化流程動態載入、外掛架構、版本不固定環境

掌握 Activator.CreateInstance + InvokeMember 模式,即可在 C# 中靈活操作任何 COM 元件,無需專案加入參考,特別適合動態擴充、外掛式架構或跨版本相容情境。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved