6

うまくいけば、質問は明確ですが、明確にするためにそれを埋めるために:

C#dllで参照している列挙型を定義するVB6dllがあります。C#dllは、戻り型が列挙型である関数を宣言するidispatchインターフェイスを使用してCCWを正しい方法で定義します。

regasmを実行すると、列挙型がCOMに表示されないため、関数がエクスポートされないという警告が表示されます。VB6ライブラリで定義されているので、COM dllで定義されているので、すでにCOMが表示されていると思います。

混乱をやめ、intを使用して列挙型を渡し、どちらかの端をキャストするだけでよいことに気付きましたが、それは適切なイライラであり、方法が存在するかどうかを知りたいと思います。

ここで要求されているのは、いくつかのサンプルコードです。

VB6dllは列挙型を定義します

Public Enum myEnum
    first = 0
    second = 1
End Enum

これは相互運用機能を介して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に表示されないと文句を言います。メタデータビューにはcomvisible属性がないため、同意する必要があります。不思議なことに、関数の引数にVB dllで定義されている他のタイプを使用すると、文句は表示されません。これは列挙型のように見えます。これは、VB6列挙型の相互運用された実装を実際に公開しているためであり、実際の列挙型。

だから私は問題を理解していると思います。私が知りたいのは、中間コードや自動生成コードのハッキングを伴わない列挙型を使用してこれを機能させる方法があるかどうかです。

4

2 に答える 2

3

解決策は、C#プロジェクトにインポートされたCOMアセンブリの「EmbedInteropTypes」プロパティをFalseに設定することのようです。

StackOverflow.ExampleComこれをテストするために、次のコードを使用してVBCOMdllを作成しました。

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#クラスプロジェクトを作成し、このStackOverflowCOMライブラリをインポートしました。次に、C#の次のコードは、VBコードで定義された列挙型を再公開するCOMオブジェクトを作成し、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; } }
    }
}

これをビルドする場合は、を使用してこのアセンブリからtypelibを作成しようとすると、regasm /tlb:EnumDemo.tlb bin\Debug\EnumDemo.dllCOM以外の可視値型の使用に関する警告が表示されます。ただし、VB COM dllへの参照で「EmbedInteropTypes」がfalseに設定されると、警告は消え、生成されたtypelibを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);
    };
    ...
于 2012-07-25T14:11:33.903 に答える
1

あなたが正しい。問題は、列挙型をコードにインポートするときに、コード内(アセンブリ内)でそれらの列挙型を使用できるようにすることです。それらを直接使用することはできません。.NETで列挙型を定義し、それらをComVisibleにする必要があります。それらは、myEnumだけでなくEnumType_myEnumとして公開されます(これを参照) 。

于 2012-07-25T13:12:55.407 に答える