With C#'s declerative programming ability it's relatively easy to expose the types to COM environment. But there are a few thing you must pay attention if you want to raise events from your managed COM component. I'll not go into the details of COM programming with C# but just focus on events for now.

Thanks to ComSourceInterfaces attribute; by using this attribute you can easily point to an interface which has the event declerations for your COM type. But before using that attribute you must have an interface to declare your type's events. (Keep in mind events are "dispatched", which means your interface that will contain the event declerations should implement IDispatch)

Here is a sample interface:

[ComVisible(true)] //Exposed

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] //Our managed interface will be IDispatch

public interface IMathEvents {

    void OnOperationCompleted(string message);


And of course we need a class that will implement that interface and expose our event to COM. Here it is:


[ComSourceInterfaces(typeof(IMathEvents))]  //Our event source is IMathEvents interface

public class Math : ServicedComponent , IMath  /*IMath interface just declares a method named Add */


  public int Add(int x, int y) {

    if (null != this.OnOperationCompleted)

    this.OnOperationCompleted("Operation completed");

    return x + y;



public delegate void OperationCompletedDel(string message); //No need to expose this delegate

public event OperationCompletedDel OnOperationCompleted;


We need the ClassInterface attribute and we need to set it to None. If we dont do that we'll end up with a class and two different interfaces one of which has the method and the other one having the event. And for example if you need to access that class from VB you'll end up with two interfaces which may be confusing such as;

Private WithEvents ? obj as IMath <--- Cannot access events ??

Private WithEvents ? obj as IMathEvents <-- Cannot access the Add method ??

But obviously we need to be able to access both the event and members ;) thanks to ClassInterface attribute. So we can:

Private WithEvents obj as Math