2017-12-07 16 views
0

私は古いCOMオブジェクトをC++/ATLで実装しています。オブジェクトには、同じ名前のイベントとプロパティがあります。これはCOMでは問題ありません。COM相互運用 - 同じ名前のイベントとプロパティ

C#では、プロパティが事実上イベントを隠すので、イベントハンドラを追加することはできないようです。

C#でこの問題を解決する方法はありますか?

(興味深いことに、WithEventsとHandlesメカニズムを使用してVB.NETで処理することはできますが、それはC#では役に立ちません)。


更新

これは、イベントインタフェース(IDL)の定義です。

// Event interface to be implemented by channel objects. 
[ 
    uuid(FF34BE60-C584-4f45-B3A1-231F0E08BE83), 
    helpstring("IChannelEvents Interface"), 
] 
dispinterface IChannelEvents 
{ 
    properties: 
    methods: 
    [id(1), helpstring("")] 
    void OnlineValue ([in] double  dValue, 
        [in] double  dMax, 
        [in] double  dMin, 
        [in] BSTR   Unit, 
        [in] VARIANT_BOOL bOverloaded); 

    [id(2), helpstring("")] 
    void MeasuredExcitation ([in] double  dValue, 
          [in] VARIANT_BOOL bValueValid, 
          [in] VARIANT_BOOL bInRange); 

    [id(3), helpstring("")] 
    void MultipleOnlineValues ([in] VARIANT  Values, 
           [in] BSTR   Unit); 
} ; 

これは、COMオブジェクト(IDL)

[ 
    uuid(2B725FC4-6FE6-4D53-9528-F098F04E98EE), 
    helpstring("Channel Class") 
] 
coclass Channel 
{ 
    [default] interface IChannel; 
    [default, source ] dispinterface IChannelEvents ; 
}; 

の定義インタフェースをそれIChannelはOnlineValueという名前のプロパティを含んでいます。私は正確な定義が重要だとは思わない。ハンスが言うように - - ので、これはエラー

Error CS1656  
Cannot assign to 'OnlineValue' because it is a 'method group' 

このコードは本当に私には意味がありませんが生成さ

class EventTest 
{ 
    void Test() 
    { 
    Channel   c = null ; 
    IChannelEvents ce = c as IChannelEvents ; 
    ce.OnlineValue += this.OnlineValue ; 
    } 

    void OnlineValue (double  dValue, 
        double  dMax, 
        double  dMin, 
        string  Unit, 
        bool   bOverloaded) 
    { 
    } 
} 

チャネルを:

ハンスはこのような何かを示唆しているようですオブジェクトはイベントインターフェイスを実装していないので、なぜChannelからIChannelEventsへのキャストが機能しますか?

+0

通常これを主張しないでくださいが、私はあなたがC#に翻訳者を介してVBコードを実行して、それがトリックをするかどうかを確認できます。両方の言語が最終的にILを作成するので、***あなたはC#で状況を処理できるはずです。 – dbugger

+0

COMオブジェクトは、例えば 'IStuff'や' _IStuffEvents_Event'(ディスパッチインタフェース1)のような2つのCOMインタフェースを実装する必要があります。これらのインターフェイスを使用してCOMインスタンスをキャストすると、あいまいさを避けることができます。 –

+0

確かにイベントインターフェイスがあります。これは、ソースインタフェースとしてIDLで定義されています。オブジェクトをそのインターフェイスに直接キャストすることはできません(実装していないため)。私は同じソースインターフェイスを持つ他のオブジェクトにキャストする必要がありますが、 '通常の'インターフェイスはありません。私はそれをする方法を知らない。 –

答えて

2

私は解決策を見つけました。これはおそらくHans Passantが示唆していたものです。

イベントインターフェイスの名前はIChannelEventsです。型ライブラリインポーターは、IChannelEvents_Eventという名前のインターフェースを生成します。次のように逆アセンブル

は、インタフェースの定義は次のとおりです。

[ComEventInterface(typeof(IChannelEvents), typeof(IChannelEvents_EventProvider)), ComVisible(false), TypeLibType(16)] 
public interface IChannelEvents_Event 
{ 
    event IChannelEvents_OnlineValueEventHandler OnlineValue; 
    event IChannelEvents_MeasuredExcitationEventHandler MeasuredExcitation; 
    event IChannelEvents_MultipleOnlineValuesEventHandler MultipleOnlineValues; 
} 

私は、このインターフェイスにCOMオブジェクトをキャストし、下図のようにイベントハンドラを追加することができます。

class EventTest 
{ 
    void Test() 
    { 
    Channel    c = null ; 
    IChannelEvents_Event ee = c as IChannelEvents_Event ; 

    ee.OnlineValue += OnlineValue ; 
    } 

    void OnlineValue (double  dValue, 
        double  dMax, 
        double  dMin, 
        string  Unit, 
        bool   bOverloaded) 
    { 
    } 
} 

このインターフェイスはIntellisenseでは表示されませんが、入力後、Visual Studioはタイプを認識するようにテキストの色を設定します。