public override bool Equals(object obj)
        {
            if (obj == null || !(obj is SingleOperate))
            {
                return(false);
            }
            SingleOperate ope = obj as SingleOperate;

            return(ope.EquipmentType == EquipmentType && ope.OperateType == OperateType);
        }
        private OperateHelper()
        {
            SingleOperConditionDic = new ObservableDictionary <SingleOperate, ObservableCollection <OperateCondition> >();

            #region 备用
            ////构造接地设备合闸条件
            //{
            //    SingleOperate so1 = new SingleOperate() { EquipmentType = typeof(Device), OperateType = SingleOperateType.合闸 };
            //    List<OperateCondition> ocList1 = new List<OperateCondition>();
            //    ocList1.Add(new OperateCondition() { PropertyMark = "合闸", PropertyName = "IsClosed", PropertyType = typeof(Switch).GetProperty("IsClosed").PropertyType, PropertyValue = false });
            //    OperateCondition oc1 = new OperateCondition() { PropertyMark = "隔离开关", PropertyType = typeof(Device).GetProperty("SwitchsRelated").PropertyType, PropertyName = "SwitchsRelated", RelatedEquipProList = ocList1 };
            //    OperateCondition oc2 = new OperateCondition() { PropertyMark = "合闸", PropertyType = typeof(Device).GetProperty("IsClosed").PropertyType, PropertyName = "IsClosed", PropertyValue = false };
            //    OperateCondition oc3 = new OperateCondition() { PropertyMark = "闭锁", PropertyType = typeof(Device).GetProperty("IsLocked").PropertyType, PropertyName = "IsLocked", PropertyValue = false };
            //    OperateCondition oc4 = new OperateCondition() { PropertyMark = "告警", PropertyType = typeof(Device).GetProperty("IsAlarming").PropertyType, PropertyName = "IsAlarming", PropertyValue = false };
            //    OperateCondition oc5 = new OperateCondition() { PropertyMark = "通过验电", PropertyType = typeof(Device).GetProperty("IsElecChecked").PropertyType, PropertyName = "IsElecChecked", PropertyValue = true };

            //    ObservableCollection<OperateCondition> list1 = new ObservableCollection<OperateCondition>();
            //    list1.Add(oc1);
            //    list1.Add(oc2);
            //    list1.Add(oc3);
            //    list1.Add(oc4);
            //    list1.Add(oc5);
            //    SingleOperConditionDic.Add(so1, list1);
            //}
            ////构造接地设备分闸条件
            //{
            //    SingleOperate so1 = new SingleOperate() { EquipmentType = typeof(Device), OperateType = SingleOperateType.分闸 };
            //    List<OperateCondition> ocList1 = new List<OperateCondition>();
            //    ocList1.Add(new OperateCondition() { PropertyMark = "门状态", PropertyName = "DoorState", PropertyType = typeof(Door).GetProperty("DoorState").PropertyType, PropertyValue = DoorState.关门 });
            //    OperateCondition oc1 = new OperateCondition() { PropertyMark = "门禁", PropertyType = typeof(Device).GetProperty("DoorsRelated").PropertyType, PropertyName = "DoorsRelated", RelatedEquipProList = ocList1 };
            //    OperateCondition oc2 = new OperateCondition() { PropertyMark = "合闸", PropertyType = typeof(Device).GetProperty("IsClosed").PropertyType, PropertyName = "IsClosed", PropertyValue = true };
            //    OperateCondition oc3 = new OperateCondition() { PropertyMark = "闭锁", PropertyType = typeof(Device).GetProperty("IsLocked").PropertyType, PropertyName = "IsLocked", PropertyValue = false };
            //    OperateCondition oc4 = new OperateCondition() { PropertyMark = "告警", PropertyType = typeof(Device).GetProperty("IsAlarming").PropertyType, PropertyName = "IsAlarming", PropertyValue = false };
            //    //OperateCondition oc5 = new OperateCondition() { PropertyType = typeof(Device).GetProperty("SwitchsRelated").PropertyType, PropertyName = "IsElecChecked", PropertyValue = true };//分闸不需要验电

            //    ObservableCollection<OperateCondition> list1 = new ObservableCollection<OperateCondition>();
            //    list1.Add(oc1);
            //    list1.Add(oc2);
            //    list1.Add(oc3);
            //    list1.Add(oc4);
            //    //list1.Add(oc5);
            //    SingleOperConditionDic.Add(so1, list1);
            //}
            #endregion


            //构造设备类基础元数据
            Type   baseType   = typeof(EquipmentBase);
            Type[] equipTypes = baseType.Assembly.GetTypes();
            foreach (var equipType in equipTypes)
            {
                if (equipType.IsSubclassOf(baseType))//是EquipmentBase的子类
                {
                    var operAttr = equipType.GetCustomAttribute <OperateTypeAttribute>(false);
                    if (operAttr != null)
                    {
                        if (operAttr.OperateType == typeof(ESingleOperateType))
                        {
                            foreach (var operType in operAttr.OperateTypeList)
                            {
                                SingleOperate so = new SingleOperate()
                                {
                                    EquipmentType = equipType, OperateType = (ESingleOperateType)operType
                                };
                                SingleOperConditionDic.Add(so, new ObservableCollection <OperateCondition>());
                            }
                        }
                        else if (operAttr.OperateType == typeof(EMultipleOperateType))
                        {
                            foreach (var operType in operAttr.OperateTypeList)
                            {
                                MultipleOperate mo = new MultipleOperate()
                                {
                                    EquipmentType = equipType, OperateType = (EMultipleOperateType)operType
                                };
                                MultiOperConditionDic.Add(mo, new ObservableCollection <SingleOperate>());
                            }
                        }
                    }

                    EquipmentSetupDic.Add(equipType.Name, new EquipmentSetup()
                    {
                        ClassName     = equipType.Name,
                        IsOperatable  = operAttr != null,
                        EquipmentName = equipType.GetCustomAttribute <OperationConfigMarkAttribute>(false)?.Mark,
                        //IsReal = false,
                        IsMultiStepOperation = operAttr.OperateType == typeof(EMultipleOperateType),
                        ClassFullName        = equipType.FullName,
                        AssemblyName         = equipType.Assembly.FullName,
                        ClassType            = equipType
                    });
                }
            }
        }
        public bool CanExecute(object param, ESingleOperateType operType)
        {
            if (!(param is EquipmentBase))
            {
                return(false);
            }
            EquipmentBase equip = param as EquipmentBase;
            SingleOperate so    = new SingleOperate()
            {
                EquipmentType = equip.GetType(), OperateType = operType
            };

            ObservableCollection <OperateCondition> operateConditionList = null;

            SingleOperConditionDic.TryGetValue(so, out operateConditionList);
            if (operateConditionList == null)
            {
                return(false);                             //(重要)没有操作条件的记录,不是没有限制随便操作,而是不能操作。没有限制的操作ConditionList为空集合而非没有
            }
            foreach (var operCondition in operateConditionList)
            {
                //找需要操作的设备中关联的设备
                Type           deviceType    = equip.GetType();
                PropertyInfo[] propertyInfos = deviceType.GetProperties();
                foreach (var propertyInfo in propertyInfos)
                {
                    if (propertyInfo.Name == operCondition.PropertyName)
                    {
                        if (propertyInfo.PropertyType.IsValueType)                                         //也可用 if (operCondition.PropertyValue != null)
                        {
                            if (propertyInfo.GetValue(equip).Equals(operCondition.PropertyValue) == false) //这里!=有问题,为什么?两个false不相等
                            {
                                return(false);
                            }
                        }
                        else if (propertyInfo.PropertyType.IsSubclassOf(typeof(EquipmentBase))) //如果是单设备
                        {
                            var relatedEquip = propertyInfo.GetValue(equip);                    //实际上必须是EquipmentBase子类
                            foreach (var relatedProp in propertyInfo.PropertyType.GetProperties())
                            {
                                foreach (var pair in operCondition.RelatedEquipProList)
                                {
                                    if (pair.PropertyName == relatedProp.Name)
                                    {
                                        if (pair.PropertyValue.Equals(relatedProp.GetValue(relatedEquip)) == false)
                                        {
                                            return(false);
                                        }
                                    }
                                }
                            }
                        }
                        //else if (propertyInfo.PropertyType.IsAssignableFrom(typeof(ICollection)))//为什么不行
                        else if (propertyInfo.GetValue(equip) is ICollection)                      //如果是集合类
                        {
                            ICollection relatedEquips = (ICollection)propertyInfo.GetValue(equip); //关联的设备
                            foreach (var relatedEquip in relatedEquips)
                            {
                                foreach (var relatedProp in relatedEquip.GetType().GetProperties())
                                {
                                    foreach (var pair in operCondition.RelatedEquipProList)
                                    {
                                        if (pair.PropertyName == relatedProp.Name)
                                        {
                                            if (pair.PropertyValue.Equals(relatedProp.GetValue(relatedEquip)) == false)
                                            {
                                                return(false);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(true);
        }
        private void InitMultipleOperDataSource()
        {
            var dataSource = new Dictionary <EquipmentSetup, Dictionary <MultipleOperate, List <SingleOperate> > >();

            foreach (var equipSetup in EquipmentSetups)
            {
                if (!equipSetup.IsMultiStepOperation)
                {
                    continue;
                }
                var tempDic     = new Dictionary <MultipleOperate, List <SingleOperate> >();
                var operateList = OperateHelper.Instance.MultiOperConditionDic.Keys.Where(p => p.EquipmentType.Name == equipSetup.ClassName).ToList();
                foreach (var operate in operateList)
                {
                    var stepList   = new List <SingleOperate>();
                    var equipProps = equipSetup.ClassType.GetProperties();
                    foreach (var equipProp in equipProps)
                    {
                        if (equipProp.GetCustomAttributes(typeof(OperationConditionAttribute), false).Length == 1)
                        {
                            string mark = (equipProp.GetCustomAttributes(typeof(OperationConfigMarkAttribute), false).FirstOrDefault() as OperationConfigMarkAttribute)?.Mark;

                            Type relatedEquipType = null;
                            if (equipProp.PropertyType.IsSubclassOf(typeof(EquipmentBase)))
                            {
                                relatedEquipType = equipProp.PropertyType;
                            }
                            else if (equipProp.PropertyType.GenericTypeArguments.Length == 1 && (typeof(IList).IsAssignableFrom(equipProp.PropertyType)) && equipProp.PropertyType.GenericTypeArguments[0].IsSubclassOf(typeof(EquipmentBase)))
                            {
                                relatedEquipType = equipProp.PropertyType.GenericTypeArguments[0];
                            }
                            else
                            {
                                continue;
                            }
                            if (relatedEquipType == null)
                            {
                                continue;
                            }
                            //获得关联设备的所有属性(TODO:根据之前的配置排序)
                            SingleOperate mo = new SingleOperate()
                            {
                                EquipmentType = relatedEquipType, OperateType = default(ESingleOperateType), EquipmentMark = mark
                            };
                            stepList.Add(mo);
                        }
                    }
                    //复制已经有的属性值
                    var singleSteps = OperateHelper.Instance.MultiOperConditionDic[new MultipleOperate()
                                                                                   {
                                                                                       EquipmentType = equipSetup.ClassType, OperateType = operate.OperateType
                                                                                   }];
                    foreach (var singleOper in singleSteps)
                    {
                        var oper = stepList.FirstOrDefault(p => p.EquipmentType == singleOper.EquipmentType);
                        if (oper != null)
                        {
                            oper.IsSelected  = singleOper.IsSelected;
                            oper.OperateType = singleOper.OperateType;
                        }
                    }
                    tempDic.Add(operate, stepList);
                }
                dataSource.Add(equipSetup, tempDic);
            }
            MultipleOperateDataSource = dataSource;
        }