簡體   English   中英

如何通過interop公開COM庫中定義的枚舉作為ac#函數的返回類型

[英]How to expose an enum defined in a COM library via interop as the return type of a c# function

希望問題很清楚,但為了清楚起見,請將其填寫清楚:

我有一個VB6 dll定義了我在C#dll中引用的枚舉。 C#dll以正確的方式定義CCW,其中idispatch接口聲明了一個函數,其返回類型是枚舉。

運行regasm時,我收到一個警告,表明枚舉不是COM可見,因此不會導出該函數。 因為它是在我的VB6庫中定義的,所以我認為它已經是COM可見的,因為它是在COM dll中定義的。

我意識到我可以停止搞亂並使用一個int傳遞枚舉,只是做任何一個結束,但它是適當的令人沮喪,我想知道是否存在一種方式。

根據要求,這里有一些示例代碼:

VB6 dll定義了一個枚舉

Public Enum myEnum
    first = 0
    second = 1
End Enum

這通過interop導入到C#中,如果您查看元數據,它看起來像這樣

[Guid("EnumGUID")]
public enum myEnum
{
    first = 0,
    second = 1        
}

然后定義CCW接口

[ComVisible(true)]
[Guid("InterfaceGuid")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMyCCWInterface
{
    [DispId(1)]
    myEnum myFunction();
}

Regasm抱怨myEnum不可見。 我必須同意它,因為元數據視圖沒有com visible屬性。 奇怪的是,如果我在VB dll中使用其他類型定義函數的參數我沒有抱怨,它似乎是枚舉,我猜它是因為我實際上暴露了VB6枚舉的交錯實現而不是實際的枚舉。

所以我想我理解這個問題,我想知道的是,如果有一種方法可以使用不涉及黑客攻擊任何中間或自動生成的代碼的枚舉。

看起來解決方案是在C#項目中為導入的COM程序集設置“嵌入互操作類型”屬性為False。

為了測試這個,我創建了一個VB COM dll作為StackOverflow.ExampleCom其中包含以下代碼

Public Enum EThing
    eThingOne = 1
    eThingTwo = 2
End Enum
Private mThing As EThing
Private Sub Class_Initialize()
    mThing = eThingOne
End Sub
Public Property Let Thing(newVal As EThing)
    mThing = newVal
End Property
Public Property Get Thing() As EThing
    Thing = mThing
End Property

然后我創建了一個C#類項目並導入了這個StackOverflow COM庫。 然后,C#中的以下代碼創建一個COM對象,該對象重新公開VB代碼中定義的枚舉類型,從而創建OP描述的相同情況。

using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using StackOverflow;

namespace EnumDemo
{
    [ComVisible(true)]
    [Guid("c30d35fe-2c7f-448b-98be-bd9be567ce70")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IEnumDemo
    {
        [DispId(1)]
        EThing Thing
        {
            get;set;
        }
    }

    [ComVisible(true)]
    [Guid("af328c82-08e3-403e-a248-8c46e27b48f3")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("StackOverflow.EnumDemo")]
    public class EnumDemo
    {
        private EThing mThing = EThing.eThingOne;
        public EThing Thing { get { return mThing; } set { mThing = value; } }
    }
}

如果我們構建它然后嘗試使用regasm /tlb:EnumDemo.tlb bin\\Debug\\EnumDemo.dll從此程序集創建一個類型庫,然后我收到有關使用非COM可見值類型的警告。 但是,一旦對VB COM dll的引用將“嵌入互操作類型”設置為false,警告就會消失,並且使用OleView檢查生成的類型庫會顯示正在使用該類型,並且已添加importlib以引用原始dll。

library EnumDemo
{
    // TLib :     // TLib :  : {D482D5CB-EE6C-455A-A28A-D26A5AC579D5}
    importlib("StackOverflow.dll");
    // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    ...
    interface IEnumDemo : IDispatch {
        [id(0x00000001), propget]
        HRESULT Thing([out, retval] EThing* pRetVal);
        [id(0x00000001), propput]
        HRESULT Thing([in] EThing pRetVal);
    };
    ...

你是對的。 問題是當您將枚舉導入代碼時,允許您在代碼中使用這些枚舉 - 在程序集內部。 您將無法直接使用它們。 您需要在.NET中定義枚舉並使它們變為ComVisible。它們將作為EnumType_myEnum公開,而不僅僅是myEnum(請參閱此內容

暫無
暫無

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

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