/// <summary> /// Adds a weak event handler info. /// </summary> /// <param name="weakHandlerInfos">The target weak event handler info collection.</param> /// <param name="target">The target instance if the event handler is a instance method; otherwise null.</param> /// <param name="methodInfo">The event handler method info.</param> /// <returns>A new weak event handler info collection.</returns> public static IEnumerable <WeakEventHandlerInfo> Add(this IEnumerable <WeakEventHandlerInfo> weakHandlerInfos, object target, MethodInfo methodInfo) { if (weakHandlerInfos == null) { throw new ArgumentNullException(nameof(weakHandlerInfos)); } if (methodInfo == null) { throw new ArgumentNullException(nameof(methodInfo)); } var newWeakHandlerInfos = new WeakEventHandlerInfo[weakHandlerInfos.Count() + 1]; // Copies existing event handler infos. int index = 0; foreach (var weakHandlerInfo in weakHandlerInfos) { newWeakHandlerInfos[index++] = weakHandlerInfo; } // Copies the new event handler info. newWeakHandlerInfos[index] = new WeakEventHandlerInfo(target, methodInfo); // Returns the weak event handler info collection. return(newWeakHandlerInfos); }
/// <summary> /// Removes a weak event handler info. /// </summary> /// <param name="weakHandlerInfos">The target weak event handler info collection.</param> /// <param name="target">The target instance if the event handler is a instance method; otherwise null.</param> /// <param name="methodInfo">The event handler method info.</param> /// <returns>A new weak event handler info collection if the event handler info is removed; otherwise the target weak event handler info collection.</returns> public static IEnumerable <WeakEventHandlerInfo> Remove(this IEnumerable <WeakEventHandlerInfo> weakHandlerInfos, object target, MethodInfo methodInfo) { if (weakHandlerInfos == null) { throw new ArgumentNullException(nameof(weakHandlerInfos)); } if (methodInfo == null) { throw new ArgumentNullException(nameof(methodInfo)); } // Finds the weak event handler info to delete. var weakHandlerInfoToDelete = weakHandlerInfos.FirstOrDefault ( weakHandlerInfo => { return(weakHandlerInfo.WeakTarget.Target == target && weakHandlerInfo.MethodInfo == methodInfo); } ); // If there is no weak event handler info to delete... if (weakHandlerInfoToDelete == null) { return(weakHandlerInfos); } var newWeakHandlerInfos = new WeakEventHandlerInfo[weakHandlerInfos.Count() - 1]; int index = 0; foreach (var weakHandlerInfo in weakHandlerInfos) { // Skips the weak event handler info to delete. if (weakHandlerInfo == weakHandlerInfoToDelete) { continue; } newWeakHandlerInfos[index++] = weakHandlerInfo; } // Returns the weak event handler info collection. return(newWeakHandlerInfos); }
/// <summary> /// Cleans up event handlers that the target objects are garbage collected. /// </summary> /// <param name="weakHandlerInfos">The target weak event handler info collection.</param> /// <param name="sender">The event sender.</param> /// <param name="args">The event arguments.</param> /// <param name="invokeHandler">If this parameter is true, alive event handlers are invoked.</param> /// <returns>A new weak event handler info collection if garbage collected event handler infos are removed; otherwise the target weak event handler info collection.</returns> public static IEnumerable <WeakEventHandlerInfo> Cleanup(this IEnumerable <WeakEventHandlerInfo> weakHandlerInfos, object sender, object args, bool invokeHandler) { if (weakHandlerInfos == null) { throw new ArgumentNullException(nameof(weakHandlerInfos)); } List <WeakEventHandlerInfo> weakHandlerInfosToDelete = null; // For each weak handler info... foreach (var weakHandlerInfo in weakHandlerInfos) { // If the event handler is a static method... if (weakHandlerInfo.MethodInfo.IsStatic) { // Calls the event handler. if (invokeHandler) { weakHandlerInfo.MethodInfo.Invoke(null, new object[] { sender, args }); } } else { // Gets the strong reference. object target = weakHandlerInfo.WeakTarget.Target; // If it is garbage collected.. if (target == null) { if (weakHandlerInfosToDelete == null) { weakHandlerInfosToDelete = new List <WeakEventHandlerInfo>(); } // Collects the garbage collected event handler info. weakHandlerInfosToDelete.Add(weakHandlerInfo); continue; } // Calls the event handler. if (invokeHandler) { weakHandlerInfo.MethodInfo.Invoke(target, new object[] { sender, args }); } } } // If no event handler info is garbage collected.. if (weakHandlerInfosToDelete == null) { return(weakHandlerInfos); } // If all event handlers are garbage collected.. int weakHandlerInfoCount = weakHandlerInfos.Count(); if (weakHandlerInfosToDelete.Count == weakHandlerInfoCount) { return(Enumerable.Empty <WeakEventHandlerInfo>()); } var newWeakHandlerInfos = new WeakEventHandlerInfo[weakHandlerInfoCount - weakHandlerInfosToDelete.Count]; int index = 0; foreach (var weakHandlerInfo in weakHandlerInfos) { // Skips the event handler info garbage collected if (weakHandlerInfosToDelete.Contains(weakHandlerInfo)) { continue; } newWeakHandlerInfos[index++] = weakHandlerInfo; } // Returns the weak event handler info collection. return(newWeakHandlerInfos); }