COMMON.cs 10.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
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<PropertyPushAttribute>() == null)
                return false;//必须是[PropertyPush]

            if (!typeof(INotifyPropertyChanged).IsAssignableFrom(propertyInfo.PropertyType))
                return false;//必须是从INotifyPropertyChanged派生的

            return true;
        }

        /// <summary>
        /// 获取全部属性, 包括父类的属性, 可能有重复的
        /// </summary>
        /// <returns></returns>
        public static List<PropertyInfo> GetAllPropertyInfos(Type interfaceType)
        {
            var interfaceTypes = new List<Type>();
            interfaceTypes.Add(interfaceType);
            interfaceTypes.AddRange(interfaceType.GetInterfaces());
            var propertyInfos = new List<PropertyInfo>();//获取全部属性, 包括父类的属性
            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<PropertyPushAttribute>() == 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<SubPropertyNode> nodes)
        {
            foreach (var node in nodes)
            {
                NodeDispose(node);
            }
        }
        public static void NodeDispose(SubPropertyNode node)
        {
            if (!node.IsArray)
            {
227
                if (node.Obj != null && node.Obj is INotifyPropertyChanged)
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
                    ((INotifyPropertyChanged)(node.Obj)).PropertyChanged -= node.PropertyChanged;
            }

            if (node.Children.Count > 0)
                NodeChildrenDispose(node.Children);

            node.Children.Clear();
            node.Obj = null;
            node.Parent = null;
        }

        /// <summary>
        /// 处理因为服务器 修改了 [PropertyPush] 的对象, 需要重新注册推送事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        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);
        }
    }

    /// <summary>
    /// 子属性节点,用于注册 INotifyPropertyChanged
    /// </summary>
    class SubPropertyNode
    {
        /// <summary>
        /// 下级节点
        /// </summary>
        public List<SubPropertyNode> Children = new List<SubPropertyNode>();
        /// <summary>
        /// 上级节点
        /// </summary>
        public SubPropertyNode Parent;
        /// <summary>
        ///  节点名称;
        ///  正常情况,就是属性的Name;
        ///  但,当为数组时, 它的下级就是数组的元素。 元素不是数组的属性。 元素的name为  $"[{序号}]"
        /// </summary>
        public string Name;
        /// <summary>
        /// 节点对象
        /// </summary>
        public object Obj;
        /// <summary>
        /// 对象的模板接口。默认就是 Obj.GetType()
        /// </summary>
        public Type InterfaceType;
        /// <summary>
        /// 是数组
        /// </summary>
        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);
}