// it is caller's responsibility to call this method under lock(rcw) public static ComEventsInfo FromObject(object rcw) { ComEventsInfo?eventsInfo = Find(rcw); if (eventsInfo == null) { eventsInfo = new ComEventsInfo(rcw); Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), eventsInfo); } return(eventsInfo); }
/// <summary> /// Adds a delegate to the invocation list of events originating from the COM object. /// </summary> /// <param name="rcw">COM object firing the events the caller would like to respond to</param> /// <param name="iid">identifier of the source interface used by COM object to fire events</param> /// <param name="dispid">dispatch identifier of the method on the source interface</param> /// <param name="d">delegate to invoke when specified COM event is fired</param> public static void Combine(object rcw, Guid iid, int dispid, Delegate d) { lock (rcw) { ComEventsInfo eventsInfo = ComEventsInfo.FromObject(rcw); ComEventsSink sink = eventsInfo.FindSink(ref iid) ?? eventsInfo.AddSink(ref iid); ComEventsMethod method = sink.FindMethod(dispid) ?? sink.AddMethod(dispid); method.AddDelegate(d); } }
/// <summary> /// Removes a delegate from the invocation list of events originating from the COM object. /// </summary> /// <param name="rcw">COM object the delegate is attached to</param> /// <param name="iid">identifier of the source interface used by COM object to fire events</param> /// <param name="dispid">dispatch identifier of the method on the source interface</param> /// <param name="d">delegate to remove from the invocation list</param> public static Delegate?Remove(object rcw, Guid iid, int dispid, Delegate d) { lock (rcw) { ComEventsInfo?eventsInfo = ComEventsInfo.Find(rcw); if (eventsInfo == null) { return(null); } ComEventsSink?sink = eventsInfo.FindSink(ref iid); if (sink == null) { return(null); } ComEventsMethod?method = sink.FindMethod(dispid); if (method == null) { return(null); } method.RemoveDelegate(d); if (method.Empty) { // removed the last event handler for this dispid - need to remove dispid handler method = sink.RemoveMethod(method); } if (method == null) { // removed last dispid handler for this sink - need to remove the sink sink = eventsInfo.RemoveSink(sink); } if (sink == null) { // removed last sink for this rcw - need to remove all traces of event info Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), null); GC.SuppressFinalize(eventsInfo); } return(d); } }
/// <summary> /// Adds a delegate to the invocation list of events originating from the COM object. /// </summary> /// <param name="rcw">COM object firing the events the caller would like to respond to</param> /// <param name="iid">identifier of the source interface used by COM object to fire events</param> /// <param name="dispid">dispatch identifier of the method on the source interface</param> /// <param name="d">delegate to invoke when specified COM event is fired</param> public static void Combine(object rcw, Guid iid, int dispid, Delegate d) { lock (rcw) { ComEventsInfo eventsInfo = ComEventsInfo.FromObject(rcw); ComEventsSink?sink = eventsInfo.FindSink(ref iid); if (sink == null) { sink = eventsInfo.AddSink(ref iid); } ComEventsMethod?method = sink.FindMethod(dispid); if (method == null) { method = sink.AddMethod(dispid); } method.AddDelegate(d); } }