Search code examples
c#com-interop

COM interop - event and property with same name


I have an old COM object implemented in C++/ATL. The object has an event and a property with the same name. This is not a problem in COM.

In C#, the property effectively hides the event, so it doesn't seem possible to add an event handler.

Is there a solution to this problem in C#?

(Interestingly, you can handle it in VB.NET using the WithEvents and Handles mechanism, but that doesn't help me in C#).


Update

This is the definition of the event interface (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 );
} ;

This it the definition of the COM object (IDL)

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

The interface IChannel contains a property named OnlineValue. I don't think the exact definition is important.

Hans seems to be suggesting something like this:

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

This generates the error

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

This code doesn't really make sense to me, because - as Hans says - the channel object does not implements the event interface, so why would the cast from Channel to IChannelEvents work?


Solution

  • I have found a solution, which is probably what Hans Passant was suggesting.

    The event interface is named IChannelEvents. The type library importer generates an interface named IChannelEvents_Event.

    Disassembled, the interface definition is as follows:

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

    I can cast the COM object to this interface and add an event handler as shown below.

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

    This interface does not show up in intellisense, but after entering it, visual Studio sets the text color to indicate that it recognizes the type.