Question

I'm not 100% positive in my code that I'm doing this right. Basically I'm making a managed COM object/library in C#. I'm doing it this way so that if someone uses my SDK they are not bound to use .NET. After reading a bunch of articles I found out that I have to make a interface for my events if my main class is going to have events. MSDN Article I read that from so I made my interface like so.

[ComVisible(true), 
Guid("A34160EA-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), 
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IBarcodeEvents
{
    //should dispid be here?
    void BarcodeDataReceived(Interfaces.IBPBarcodeDevice device);
}

Then I read that VB6 really needs/wants to have a DispID attribute. (A unique one per com object) but I'm confused. Do I put the DispId in my IBarcodeEvents or in IBPBarcodeDevice (comments removed for brevity)

[Guid("96CB4F45-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), ComVisible(true)]
public interface IBPBarcodeDevice : IBarcodeEvents
{
    [DispId(5001)]
    Data.BarcodeData GetBarcodeData();
    [DispId(5002)]
    bool HasBarcodeData();
    [DispId(5003)]
    void EnableBarcodeScanner();
    [DispId(5004)]
    void DisableBarcodeScaner();

    [DispId(5101)]
    event BarcodeDataReceivedHandler BarcodeDataReceived;
}
Was it helpful?

Solution

Sure, the members of an IDispatch interface require a dispid to make late binding work. It is what powers the IDispatch::Invoke() function. It is so important that the type library exporter will auto-generate them if you omit the [DispId] attributes. Which by itself already does a fine job. As long as you pick arbitrary numbers like 5001 then there is no point in avoiding the auto-generated ones. It will not work "better".

  public interface IBPBarcodeDevice : IBarcodeEvents

This is not correct, the events interface must be separate from the interfaces that expose methods like EnableBarcodeScanner(). An event interface only appears in your [ComSourceInterfaces] attribute and nowhere else. It is the job of the event listener to implement it, not the event source. The listener is the one that gets the callbacks on its BarcodeDataReceived() method. Or to put it another way, you don't listen to your own events, only the client code is interested in them and it must therefore implement IBarcodeEvents. It must not implement IBPBarcodeDevice.

Review the MSDN example, note how the Button class does not implement the ButtonEvents interface. The binding between the event you declare in your class and the interface methods that the client implements is part of the standard COM plumbing that any language runtime implements.

Which answers your question, you apply the attributes to the IBarcodeEvents methods. But since the actual values never matter for event interface methods you can simply omit them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top