簡體   English   中英

如何在 VB6 和 C# 之間共享接口?

[英]How can I share an interface between VB6 and C#?

我希望能夠編寫一個可以在 C# 和 VB6 類中實現的類接口,以便可以在 VB6 代碼中以相同的方式處理這些類,但我無法完成這項工作。

在VB6中,我想使用Implements關鍵字來實現類VB6Class來實現一些接口ISharedInterface。

在 C# 中,我想要一些其他類 C#Class,我可以將它們公開給 COM,同時實現 ISharedInterface。

目標是 VB6 代碼將能夠通過 ISharedInterface 對 VB6Class 和 C#Class 進行操作,而無需關心這些類是用哪種語言構建的。

我想使用這種技術作為一種從 VB6 遷移的方法,通過在 VB6 端連續重寫所有內容,如果我可以在 C# 中實現我在 VB6 中已有的接口,這將是理想的。 但是失敗了,即使我必須用 C# 重寫一個接口以共享回 VB6,這仍然很有用(即,我什至不關心接口是用 C# 編寫並暴露給 COM 還是用 COM 編寫並由C#,只要語言不通的雙方都能引用同一個接口即可)。

我發現這出奇地難。 我可以在 C# 中引用來自 COM 的接口,但我無法將其作為 COM 可見接口導出回 COM。 作為替代方案,如果我嘗試在 C# 本身中創建一個接口,我還沒有找到直接通過 COM 查看它的方法,以及我嘗試間接使用它的各種解決方法,例如創建一個存根類來實現接口並公開當我嘗試實現公開的存根類(即使它們編譯)時,COM 可見只是在 VB6 中引發運行時錯誤。

我目前對此沒有好的解決方案,只有一個非常笨拙的工作,即在 C# 和 VB6 中實現單獨的接口,將 C# 方法直接公開給 COM 並在 VB6 中創建一個包裝類,該類簡單地將接口方法重定向到底層 true方法。

創建兩種語言都可以引用的單個接口(在 VB6 或 C# 中)的最佳方法是什么,而我不必復制接口定義?

創建兩種語言都可以引用的單個接口(在 VB6 或 C# 中)的最佳方法是什么,而我不必復制接口定義?

在 IDL 中編寫接口並編譯成一個類型庫,該庫在 VB 中引用並導入( tlbimp )到 .NET 中。 (如果您使用它來定義接口,則需要避免 VB6 將執行的 IID 的重新生成。)

您可以在 .NET 中定義接口,但這將涉及更多步驟。

我不確定我是否誤解了這個問題,但是您為什么要在 VB6 中實現該接口? 如果您有一個在 VB6 和 C# 中實現的接口,那么您可能會復制基本上做相同事情的代碼。 如果您正致力於從 VB6 遷移,您可能希望限制您編寫的 VB6 代碼量。

我目前正在使用一個大型 VB6 應用程序,所有新的開發都是在 C# 中完成的。 我有大約一打 C# 程序集,其中只有一個公開了 COM。 它只是一個小程序集,通過 COM 公開我需要的方法,因此我可以直接在我的 VB6 項目中使用。 您可以在 VB6 中創建一個包裝類,就像您說的那樣,以集中調用 C# 程序集。 這就是我在我們的項目中所做的,因此包裝器可以在第一次使用程序集時初始化對程序集的引用,而不是每次使用時都這樣做。

因此,聽起來您目前使用的“笨拙”解決方法更符合我所做的工作。 也許主要區別在於我沒有將任何實際的 C# 方法公開給 COM。 這一切都在我的 COM 接口程序集中完成。 當需要拋棄 VB6 代碼時,COM 接口程序集就被扔掉了,其余的 C# 代碼/程序集與 COM 沒有關系。 我們已經有一些其他產品共享相同的 C# 程序集,它們只是直接引用它們,因此一旦 COM 接口被丟棄,它們就不會受到影響。

創建一個 C# 類庫(在本例中稱為 DemoComInterface)並確保未選中“使程序集 COM 可見”。 (提醒一下,以下代碼片段中的 GUID 應替換為您自己的唯一 GUID。)

給類庫添加一個接口,像這樣:

using System.Runtime.InteropServices;

namespace DemoComInterface
{
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [ComVisible(true)]
    [Guid("01B0A84D-CACE-4EF1-9C4B-6995A71F9AB8")]
    public interface ISharedInterface
    {
        [DispId(0x60030040)]
        void Question();
    }
}

要使用共享接口演示 C# 類,請更新 Class1 以實現共享接口,並使用以下屬性對其進行修飾:

using System.Runtime.InteropServices;

namespace DemoComInterface
{
    [Guid("CC9A9CBC-054A-4C9C-B559-CE39A5EA2742")]
    [ProgId("DemoComInterface.Class1")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComVisible(true)]
    public class Class1 : ISharedInterface
    {
        public void Question()
        {
            throw new NotImplementedException();
        }
    }
}

現在,將您的 AssemblyInfo.cs 文件的 AssemblyDescription 屬性修改為有意義的內容,以便可以在 VB6 的“參考”瀏覽器中找到類型庫。 這可以通過直接編輯文件或填充裝配信息對話框的“描述”字段來完成。

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DemoComInterface")]
// This is what will be seen in VB6's 'References' browser.**
[assembly: AssemblyDescription("Demo C# exported interfaces")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DemoComInterface")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4294f846-dd61-418d-95cc-63400734c876")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

通過檢查項目的“注冊 COM 互操作”構建屬性或使用 REGASM 在命令提示符中手動注冊此類庫,可以注冊此類庫。

查看生成的類型庫(在項目的 bin 輸出文件夾中),您應該看到如下內容:

// Generated .IDL file (by the OLE/COM Object Viewer)
// 
// typelib filename: DemoComInterface.tlb

[
uuid(4294F846-DD61-418D-95CC-63400734C876),
version(1.0),
helpstring("Demo C# exported interfaces"),
custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "DemoComInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

]
library DemoComInterface
{
    // TLib :     // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    importlib("mscorlib.tlb");
    // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface ISharedInterface;

    [
    uuid(CC9A9CBC-054A-4C9C-B559-CE39A5EA2742),
    version(1.0),
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "DemoComInterface.Class1")
    ]
    coclass Class1 {
        interface _Object;
        [default] interface ISharedInterface;
    };

    [
    odl,
    uuid(01B0A84D-CACE-4EF1-9C4B-6995A71F9AB8),
    version(1.0),
    dual,
    oleautomation,
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "DemoComInterface.ISharedInterface")    

    ]
    interface ISharedInterface : IDispatch {
        [id(0x60030040)]
        HRESULT Question();
    };
};

共享接口現在在 COM 可見的 C# 類中實現。

要在 VB6 項目中實現共享接口,請添加對“Demo C# 導出接口”的引用,並按如下方式實現:

Option Explicit

Implements ISharedInterface
    
' Implementation of Question.
Public Sub ISharedInterface_Question()
    MsgBox ("Who is number one?")
End Sub

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM