偶遇需要避免重复注册事件引起的内存泄漏
这个问题会出现在数据绑定到界面的时候,由于重新New了一个Element去显示而造成的事件注册没有取消
此项已经更新,主要在于当前Field查找字段的时候只能查找当前Type的类型,现更改为可以向上查找父级,返回第一个查找到的字段,那么在注册的时候就不用指定写继承了INotifyPropertyChanged 或者 INotifyCollectionChanged的类型了
1 /* 迹I柳燕 2 * 3 * FileName: JisonsINotifyOfInvocationList.cs 4 * Version: 1.0 5 * Date: 2014.03.18 6 * Author: Ji 7 * 8 *======================================== 9 * @namespace Jisons 10 * @class JisonsINotifyOfInvocationList 11 * @extends 12 * 13 * WPF 扩展 14 * 对于实现 INotify 接口的委托链 增 删 委托的处理 15 * 16 *======================================== 17 * Hi,小喵喵... 18 * Copyright © 迹I柳燕 19 * 20 * 转载请保留... 21 * 22 */ 23 24 using System; 25 using System.Collections.Specialized; 26 using System.ComponentModel; 27 using System.Linq; 28 using System.Reflection; 29 30 namespace Jisons 31 { 32 public static class JisonsINotifyOfInvocationList 33 { 34 35 ///增加委托到 _invocationList 委托列表中 ,执行重复检查 36 ///具有 _invocationList 链的类型 37 /// 具有线程通知的数据,此项为原委托链的数据类型 38 /// 增加到委托链的委托 39 /// 当前类型是否为 INotifyCollectionChanged 40 ///执行增加是否成功 41 static bool JudgeAddEventHandler(this object data, Delegate handler, bool isINotifyCollectionChanged) 42 { 43 bool canAdd_invocation = false; 44 45 if (data == null) 46 { 47 return canAdd_invocation; 48 } 49 try 50 { 51 var collectionchangedValue = handler; 52 var flag = BindingFlags.Instance | BindingFlags.NonPublic; 53 54 string changed = string.Empty; 55 FieldInfo judgechanged = null; 56 if (isINotifyCollectionChanged) 57 { 58 changed = "CollectionChanged"; 59 judgechanged = typeof(T).FindField(changed, flag); 60 } 61 else 62 { 63 changed = "PropertyChanged"; 64 judgechanged = typeof(T).FindField(changed, flag); 65 } 66 67 if (judgechanged == null) 68 { 69 return canAdd_invocation; 70 } 71 72 var collectionvalue = judgechanged.GetValue(data); 73 if (collectionvalue != null) 74 { 75 var collectionlist = typeof(MulticastDelegate).FindField("_invocationList", flag).GetValue(collectionvalue) as object[]; 76 if (collectionlist != null) 77 { 78 #region Judge Distinct 79 80 //In This Way To Remove The Same Handler 81 //At Fact, I Want To Remove The Handler When I Add If ( collectionlist == null) 82 83 var collectionlistdistinct = collectionlist.Distinct().ToList(); 84 int collectioncount = collectionlist.Count() - 1; 85 for (int i = collectioncount; i >= 0; i--) 86 { 87 var item = collectionlist[i]; 88 if (item != null) 89 { 90 if (collectionlistdistinct.Contains(item)) 91 { 92 collectionlistdistinct.Remove(item); 93 } 94 else 95 { 96 Delegate collectionchangedValueTemp = null; 97 if (isINotifyCollectionChanged) 98 { 99 collectionchangedValueTemp = item as NotifyCollectionChangedEventHandler;100 }101 else102 {103 collectionchangedValueTemp = item as PropertyChangedEventHandler;104 }105 106 if (collectionchangedValueTemp != null)107 {108 var method = typeof(T).GetEvent(changed);109 if (method != null)110 {111 method.RemoveEventHandler(data, collectionchangedValueTemp);112 }113 }114 }115 }116 }117 118 #endregion119 120 if (collectionlist != null && !collectionlist.Contains(collectionchangedValue))121 {122 canAdd_invocation = true;123 }124 }125 126 //In The Second To Add Handle , Can Not Find The Data Of collectionlist127 else128 {129 var method = typeof(T).GetEvent(changed);130 method.RemoveEventHandler(data, collectionchangedValue);131 method.AddEventHandler(data, collectionchangedValue);132 }133 }134 else135 {136 canAdd_invocation = true;137 }138 139 if (canAdd_invocation)140 {141 var method = typeof(T).GetEvent(changed);142 method.AddEventHandler(data, collectionchangedValue);143 }144 }145 catch146 {147 throw new Exception("Add Event Handler Unsuccess ...");148 }149 150 return canAdd_invocation;151 }152 153 /// 清空具有 _invocationList 的委托列表 154 ///具有 _invocationList 链的类型 155 /// 具有线程通知的数据156 /// 删除指定类型中的所有此类型注册委托157 /// 当前类型是否为 INotifyCollectionChanged158 ///执行删除是否成功 159 static bool JudgeRemoveEventHandler(this object data, object remove_targetdata, bool isINotifyCollectionChanged)160 {161 if (data == null)162 {163 return false;164 }165 166 bool canRemove_invocation = false;167 168 var flag = BindingFlags.Instance | BindingFlags.NonPublic;169 170 string changed = string.Empty;171 FieldInfo judgechanged = null;172 if (isINotifyCollectionChanged)173 {174 changed = "CollectionChanged";175 judgechanged = typeof(T).FindField(changed, flag);176 }177 else178 {179 changed = "PropertyChanged";180 judgechanged = typeof(T).FindField(changed, flag);181 }182 183 if (judgechanged == null)184 {185 return canRemove_invocation;186 }187 188 var collectionvalue = judgechanged.GetValue(data);189 if (collectionvalue != null)190 {191 var collectionlist = typeof(MulticastDelegate).FindField("_invocationList", flag).GetValue(collectionvalue) as object[];192 if (collectionlist != null)193 {194 int collectioncount = collectionlist.Count() - 1;195 for (int i = collectioncount; i >= 0; i--)196 {197 var item = collectionlist[i];198 if (item != null)199 {200 var target = typeof(Delegate).FindField("_target", flag).GetValue(item);201 bool canRemove = target == null || target.Equals(remove_targetdata);202 if (canRemove)203 {204 Delegate collectionchangedValueTemp = null;205 if (isINotifyCollectionChanged)206 {207 collectionchangedValueTemp = item as NotifyCollectionChangedEventHandler;208 }209 else210 {211 collectionchangedValueTemp = item as PropertyChangedEventHandler;212 }213 214 if (collectionchangedValueTemp == null)215 {216 return canRemove_invocation;217 }218 219 var method = typeof(T).GetEvent(changed);220 method.RemoveEventHandler(data, collectionchangedValueTemp);221 canRemove_invocation = true;222 }223 }224 }225 }226 }227 228 return canRemove_invocation;229 }230 231 /// 对 INotifyPropertyChanged 的委托链增加委托函数 232 ///具有线程通知的传入类型 233 /// 实现线程通知的类型234 /// 将要增加的委托235 ///是否增加成功 236 public static bool AddPropertyEventHandler(this INotifyPropertyChanged property, PropertyChangedEventHandler handler)237 {238 return JudgeAddEventHandler (property, handler, false);239 }240 241 /// 对 INotifyCollectionChanged 的委托链增加委托函数 242 ///具有线程通知的传入类型 243 /// 实现线程通知的类型244 /// 将要增加的委托245 ///是否增加成功 246 public static bool AddCollectionEventHandler(this INotifyCollectionChanged collection, NotifyCollectionChangedEventHandler handler)247 {248 return JudgeAddEventHandler (collection, handler, true);249 }250 251 /// 对 INotifyPropertyChanged 的委托链删除指定Target的委托函数 252 ///具有线程通知的传入类型 253 /// 将要增加的委托254 /// 255 ///是否删除成功 256 public static bool RemovePropertyEventHandler(this INotifyPropertyChanged property, object remove_targetdata)257 {258 return JudgeRemoveEventHandler (property, remove_targetdata, false);259 }260 261 /// 对 INotifyCollectionChanged 的委托链删除指定Target的委托函数 262 ///具有线程通知的传入类型 263 /// 实现线程通知的类型264 /// 将要增加的委托265 ///是否删除成功 266 public static bool RemoveCollectionEventHandler(this INotifyCollectionChanged collection, object remove_targetdata)267 {268 return JudgeRemoveEventHandler (collection, remove_targetdata, true);269 }270 271 }272 }
此项为 FindField
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection; 5 using System.Text; 6 7 namespace Jisons 8 { 9 public static class JisonsFindClassInfo 10 { 11 12 ///从当前类型一直向上查找指定名称的字段 13 /// 查找的起始类型 14 /// 字段的名称 15 /// 搜索的标志 16 ///返回查询到的 FieldInfo 17 public static FieldInfo FindField(this Type type, string fieldName, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic) 18 { 19 if (!string.IsNullOrWhiteSpace(fieldName)) 20 { 21 var field = type.GetField(fieldName, bindingAttr); 22 if (field != null) 23 { 24 return field; 25 } 26 else if (type.BaseType != null) 27 { 28 return type.BaseType.FindField(fieldName, bindingAttr); 29 } 30 } 31 return null; 32 } 33 34 ///从当前类型一直向上查找指定名称的属性 35 /// 查找的起始类型 36 /// 属性的名称 37 /// 搜索的标志 38 ///返回查询到的 PropertyInfo 39 public static PropertyInfo FindProperty(this Type type, string propertyName, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic) 40 { 41 if (!string.IsNullOrWhiteSpace(propertyName)) 42 { 43 var property = type.GetProperty(propertyName, bindingAttr); 44 if (property != null) 45 { 46 return property; 47 } 48 else if (type.BaseType != null) 49 { 50 return type.BaseType.FindProperty(propertyName, bindingAttr); 51 } 52 } 53 return null; 54 } 55 56 ///查询当前程序集所拥有的指定类型字段字段元数据集合 57 ///指定查询的类型 58 /// 查选的程序集 59 /// 查询的指定参数 60 ///查询到的字段元数据集合 61 public static IListFindFieldInAssembly (this Assembly assembly, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic) where T : class 62 { 63 IList datas = new List (); 64 65 var classTypes = assembly.GetTypes(); 66 foreach (var item in classTypes) 67 { 68 var fields = item.GetFields(bindingAttr); 69 if (fields.Count() > 0) 70 { 71 var fieldType = typeof(T); 72 //此处在大量数据时曾试过并行获取 Parallel.ForEach 73 //不幸的发现会更慢 74 foreach (var field in fields) 75 { 76 if (field.FieldType.Equals(fieldType)) 77 { 78 datas.Add(field); 79 } 80 } 81 } 82 } 83 84 return datas; 85 } 86 87 /// 查询当前程序集所拥有的指定类型静态字段集合 88 ///指定查询的类型 89 /// 查选的程序集 90 /// 查询的指定参数 91 ///查询到指定静态类型的值集合 92 public static IListFindStaticFieldValueInAssembly (this Assembly assembly, BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public) where T : class 93 { 94 IList datas = new List (); 95 96 var fieldList = assembly.FindFieldInAssembly (bindingAttr); 97 if (fieldList.Count > 0) 98 { 99 //此处在大量数据时曾试过并行获取 Parallel.ForEach100 //不幸的发现会更慢101 fieldList.ForEach(i =>102 {103 var data = i.GetValue(null) as T;104 if (data != null)105 {106 datas.Add(data);107 }108 });109 }110 111 return datas;112 }113 114 /// 查询当前程序集所拥有的指定类型接口的接口元数据集合 115 ///指定查询类型的接口 116 /// 查选的程序集 117 /// 查询的指定参数 118 ///查询到的字段元数据集合 119 public static IDictionaryFindInterfacesInAssembly (this Assembly assembly, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic) where T : class120 {121 IDictionary datas = new Dictionary ();122 123 var classTypes = assembly.GetTypes();124 var returnType = typeof(T).Name;125 foreach (var item in classTypes)126 {127 var interfaces = item.GetInterfaces();128 if (interfaces.Count() > 0)129 {130 var interfaceOfT = interfaces.FirstOrDefault(i => i.Name.Equals(returnType));131 if (interfaceOfT != null)132 {133 datas.Add(item, interfaceOfT);134 }135 }136 }137 return datas;138 }139 140 /* test141 142 * /// 获取继承接口而实现添加的快捷键子项集合 143 /// 144 ///145 public static List GetInterfaceHotKeys(this Assembly currentAssembly)146 {147 var referencedAssemblies = currentAssembly.GetReferencedAssemblies().ToList();148 referencedAssemblies.Add(currentAssembly.GetName());149 150 List datas = new List ();151 Parallel.ForEach(referencedAssemblies, referencedAssembly =>152 {153 var assembly = Assembly.Load(referencedAssembly);154 var data = assembly.FindInterfacesInAssembly ();155 if (data != null)156 {157 foreach (var interfaceDictionary in data)158 {159 var methods = interfaceDictionary.Value.GetMethods();160 var returnType = typeof(List );161 var methodOfIHotKeys = methods.FirstOrDefault(i => i.ReturnType.Equals(returnType));162 if (methodOfIHotKeys != null)163 {164 var property = interfaceDictionary.Key.FindProperty("CurrenttRoutedCommandsTarget", BindingFlags.Instance | BindingFlags.Public);165 if (property != null)166 {167 try168 {169 //此时线程并不在UI线程,切要优化效率因此并不做移交到UI线程处理170 //因此,实现接口的函数不能是需要在UI线程创建的class,例如UIElement171 object obj = interfaceDictionary.Key.GetConstructor(Type.EmptyTypes).Invoke(null);172 var value = methodOfIHotKeys.Invoke(obj, null) as List ;173 if (value != null)174 {175 datas.AddRange(value);176 }177 }178 catch (Exception ex)179 {180 Console.WriteLine(ex.Message);181 }182 }183 }184 }185 }186 });187 188 return datas;189 }190 191 * */192 193 }194 }