2017-12-07 1 views
0

Ich habe ein altes COM-Objekt in C++/ATL implementiert. Das Objekt hat ein Ereignis und eine Eigenschaft mit demselben Namen. Dies ist kein Problem in COM.COM Interop - Ereignis und Eigenschaft mit dem gleichen Namen

In C# blendet die Eigenschaft das Ereignis effektiv aus, daher scheint es nicht möglich, einen Ereignishandler hinzuzufügen.

Gibt es eine Lösung für dieses Problem in C#?

(Interessanterweise können Sie in VB.NET mit dem WithEvents und Handles-Mechanismus umgehen, aber das hilft mir nicht in C#).


aktualisieren

Dies ist die Definition der Ereignisschnittstelle (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); 
} ; 

Dieses es die Definition des COM-Objekts (IDL)

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

Die Schnittstelle IChannel eine Eigenschaft enthält namens OnlineValue. Ich denke nicht, dass die genaue Definition wichtig ist.

Hans scheint so etwas zu werden, was darauf hindeutet:

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) 
    { 
    } 
} 

der Fehler dadurch nicht

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

Dieser Code erzeugt nicht wirklich Sinn für mich, weil - wie Hans sagt - den Kanal Das Objekt implementiert die Ereignisschnittstelle nicht. Warum also funktioniert die Umwandlung von Channel zu IChannelEvents?

+0

Normalerweise befürworten Sie dies nicht, aber ich würde sehen, ob Sie den VB-Code über einen Übersetzer auf C# ausführen könnten, um zu sehen, ob das funktioniert. Da beide Sprachen letztendlich IL erzeugen, sollten Sie in der Lage sein, die Situation in C# zu behandeln. – dbugger

+0

Das COM-Objekt sollte zwei COM-Schnittstellen implementieren, z. B. "ISTuff" und "_IStuffEvents_Event" (die Dispatchschnittstelle). Sie können die Mehrdeutigkeit vermeiden, wenn Sie die COM-Instanz mithilfe dieser Schnittstellen umwandeln. –

+0

Sicher gibt es eine Ereignisschnittstelle. Es ist in IDL als Quellschnittstelle definiert. Ich kann das Objekt nicht direkt auf diese Schnittstelle anwenden (weil es es nicht implementiert). Ich müsste es auf ein anderes Objekt mit derselben Quellschnittstelle umwandeln, aber ohne die "normale" Schnittstelle. Ich weiß nicht, wie ich das machen soll. –

Antwort

2

Ich habe eine Lösung gefunden, die wahrscheinlich Hans Passant vorgeschlagen hat.

Die Ereignisschnittstelle heißt IChannelEvents. Das Typbibliothekimportierer generiert eine Schnittstelle namens IChannelEvents_Event.

Zerlegt wird die Interface-Definition wie folgt:

[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; 
} 

ich das COM-Objekt auf diese Schnittstelle umgewandelt und einen Ereignishandler hinzufügen, wie unten gezeigt.

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) 
    { 
    } 
} 

Diese Schnittstelle zeigt nicht in IntelliSense, aber es, Visual Studio setzt die Textfarbe nach der Eingabe, um anzuzeigen, dass sie den Typ erkennt.