using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace FObjBase.Reflect { static class COMMON { static bool IsPropertyPush(PropertyInfo propertyInfo) { if (propertyInfo.GetCustomAttribute() == null) return false;//必须是[PropertyPush] if (!typeof(INotifyPropertyChanged).IsAssignableFrom(propertyInfo.PropertyType)) return false;//必须是从INotifyPropertyChanged派生的 return true; } /// /// 获取全部属性, 包括父类的属性, 可能有重复的 /// /// public static List GetAllPropertyInfos(Type interfaceType) { var interfaceTypes = new List(); interfaceTypes.Add(interfaceType); interfaceTypes.AddRange(interfaceType.GetInterfaces()); var propertyInfos = new List();//获取全部属性, 包括父类的属性 foreach (var ifaceType in interfaceTypes) { propertyInfos.AddRange(ifaceType.GetProperties()); } return propertyInfos; } public static void InitPropertyPush(SubPropertyNode rootNode) { //处理[PropertyPush] var propertyInfos = GetAllPropertyInfos(rootNode.InterfaceType); foreach (var propertyInfo in propertyInfos) { if (propertyInfo.GetCustomAttribute() == null) continue;//必须是[PropertyPush] SubPropertyNode node = new SubPropertyNode(); if (ReInitPropertyPush(node, rootNode.Obj, propertyInfo, rootNode.SubPropertyChanged)) { node.Parent = rootNode; rootNode.Children.Add(node); } } } public static bool ReInitPropertyPush(SubPropertyNode node, object parentObj, PropertyInfo propertyInfo, SubPropertyChangedEventHandler sub_PropertyChanged) { var propertyValue = propertyInfo.GetValue(parentObj); // propertyValue==null 也注册 if (typeof(INotifyPropertyChanged).IsAssignableFrom(propertyInfo.PropertyType)) { //必须是从INotifyPropertyChanged派生的 node.Name = propertyInfo.Name; node.InterfaceType = propertyInfo.PropertyType; node.Obj = propertyValue; node.SubPropertyChanged = sub_PropertyChanged; if (node.Obj != null) { //下级推送!!!! ((INotifyPropertyChanged)(propertyValue)).PropertyChanged += node.PropertyChanged; InitSubPropertyPush(propertyValue, node, sub_PropertyChanged); } return true; } else if (typeof(System.Collections.IList).IsAssignableFrom(propertyInfo.PropertyType)) { //数组 node.Name = propertyInfo.Name; node.InterfaceType = propertyInfo.PropertyType; node.Obj = propertyValue; node.IsArray = true; var list = node.Obj as System.Collections.IList; if (list != null && list.Count > 0) { InitSubPropertyPushs(list, node, sub_PropertyChanged); } return true; } return false; } static void InitSubPropertyPush(object obj, SubPropertyNode node, SubPropertyChangedEventHandler sub_PropertyChanged) { //继续向下找 var propertyInfos = obj.GetType().GetProperties(); foreach (var propertyInfo in propertyInfos) { if (!IsPropertyPush(propertyInfo)) continue;//必须是[PropertyPush] var element = propertyInfo.GetValue(obj); var node_sub = new SubPropertyNode() { Name = propertyInfo.Name, InterfaceType = propertyInfo.PropertyType, Obj = element, Parent = node, SubPropertyChanged = sub_PropertyChanged }; //下级推送!!!! ((INotifyPropertyChanged)(element)).PropertyChanged += node_sub.PropertyChanged; node.Children.Add(node_sub); InitSubPropertyPush(element, node_sub, sub_PropertyChanged); } } static void InitSubPropertyPushs(System.Collections.IList list, SubPropertyNode node, SubPropertyChangedEventHandler sub_PropertyChanged) { for (int i = 0; i < list.Count; i++) { var element = list[i]; if (element == null) { //空的。。。 continue; } var elementType = element.GetType(); if (!typeof(INotifyPropertyChanged).IsAssignableFrom(elementType)) { //异常!!!! continue; } var node_sub = new SubPropertyNode() { Name = $"[{i}]", InterfaceType = elementType, Obj = element, Parent = node, SubPropertyChanged = sub_PropertyChanged }; //下级推送!!!! ((INotifyPropertyChanged)(element)).PropertyChanged += node_sub.PropertyChanged; node.Children.Add(node_sub); InitSubPropertyPush(element, node_sub, sub_PropertyChanged); } } public static string GetNodePath(SubPropertyNode node) { if (string.IsNullOrEmpty(node.Name)) { //已经是最上级 return null; } StringBuilder sb = new StringBuilder(); sb.Append(node.Name); while (node.Parent != null) { node = node.Parent; if (string.IsNullOrEmpty(node.Name)) { //到了最上级 break; } sb.Insert(0, node.Name + "."); } return sb.ToString(); } public static SubPropertyNode FindNode(SubPropertyNode rootNode, string path) { SubPropertyNode node = null; if (string.IsNullOrEmpty(path)) return rootNode; var nodes = rootNode.Children; //分解路径 string[] names = path.Split('.'); foreach (string name in names) { if (string.IsNullOrEmpty(name)) { //这个不算 continue; } node = nodes.Find(n => n.Name == name); if (node == null) { //异常 return null; } nodes = node.Children; } return node; } public static void NodeChildrenDispose(List nodes) { foreach (var node in nodes) { NodeDispose(node); } } public static void NodeDispose(SubPropertyNode node) { if (!node.IsArray) { if (node.Obj != null) ((INotifyPropertyChanged)(node.Obj)).PropertyChanged -= node.PropertyChanged; } if (node.Children.Count > 0) NodeChildrenDispose(node.Children); node.Children.Clear(); node.Obj = null; node.Parent = null; } /// /// 处理因为服务器 修改了 [PropertyPush] 的对象, 需要重新注册推送事件 /// /// /// public static void PropertyChanged_reInitPropertyPush(SubPropertyNode node, PropertyChangedEventArgs e) { var sub_node = node.Children.Find(n => n.Name == e.PropertyName); if (sub_node == null) return; //这个被修改了 //卸载它 COMMON.NodeDispose(sub_node); var propertyInfo = node.Obj.GetType().GetProperty(e.PropertyName); //重新注册 COMMON.ReInitPropertyPush(sub_node, node.Obj, propertyInfo, node.SubPropertyChanged); } } /// /// 子属性节点,用于注册 INotifyPropertyChanged /// class SubPropertyNode { /// /// 下级节点 /// public List Children = new List(); /// /// 上级节点 /// public SubPropertyNode Parent; /// /// 节点名称; /// 正常情况,就是属性的Name; /// 但,当为数组时, 它的下级就是数组的元素。 元素不是数组的属性。 元素的name为 $"[{序号}]" /// public string Name; /// /// 节点对象 /// public object Obj; /// /// 对象的模板接口。默认就是 Obj.GetType() /// public Type InterfaceType; /// /// 是数组 /// public bool IsArray; public PropertyChangedEventHandler PropertyChanged; public SubPropertyChangedEventHandler SubPropertyChanged; public SubPropertyNode() { PropertyChanged = new PropertyChangedEventHandler(_PropertyChanged); } public void _PropertyChanged(object sender, PropertyChangedEventArgs e) { //处理[PropertyPush]重新注册问题 COMMON.PropertyChanged_reInitPropertyPush(this, e); SubPropertyChanged?.Invoke(this, e); } } delegate void SubPropertyChangedEventHandler(SubPropertyNode node, PropertyChangedEventArgs e); }