private void DepthBuild(BuildTreeNode <CustomBuildTreeNodeConfig> buildNode, PropertiesTreeNode newNode) { // Создаём другие node дерева. List <PropertiesTreeNode> newNodes = new List <PropertiesTreeNode>(); foreach (var nodePair in buildNode.ChildNodes) { //string propName = nodePair.Key; //if (buildNode.Config.IgnoredProperties.Contains(propName)) // continue; var newInnerNode = new PropertiesTreeNode(nodePair.Value.Property); // Если это поле if (buildNode.Config.GoDepthProperties.Contains(newInnerNode.PropertyName)) { DifferenceSearchBuilderExtensions.AutoDepthBuild(newInnerNode.PropertyType, newInnerNode); } else { DepthBuild(nodePair.Value, newInnerNode); } newNodes.Add(newInnerNode); } newNode.InnerProperties = buildNode.Config.NeedAllProperties ? buildNode.PropertyType.GetProperties() : buildNode.Config.SelectedProperties.ToArray(); newNode.Nodes = newNodes.ToArray(); }
public void Build() { PropertiesTreeNode root = new PropertiesTreeNode(typeof(TSource)); DepthBuild(_buildRootNode, root); PropertyTree = root; }
private PropertyDifference[] GetDifferences(PropertiesTreeNode node, object firstObj, object secondObj) { List <PropertyDifference> differences = new List <PropertyDifference>(); foreach (PropertyInfo info in node.InnerProperties) { var left = info.GetValue(firstObj); var right = info.GetValue(secondObj); if (left == right) { continue; } if (left == null || right == null || !left.Equals(right)) { differences.Add(new PropertyDifference { ClassType = node.PropertyType, PropertyType = info.PropertyType, PropertyName = info.Name, ValueLeft = left, ValueRight = right }); } } foreach (var childNode in node.Nodes) { var left = childNode.Property.GetValue(firstObj); var right = childNode.Property.GetValue(secondObj); if (left == right) { continue; } if (left == null || right == null) { differences.Add(new PropertyDifference { ClassType = node.PropertyType, PropertyType = childNode.PropertyType, PropertyName = childNode.PropertyName, ValueLeft = left, ValueRight = right }); continue; } var newDiffs = GetDifferences(childNode, left, right); differences.AddRange(newDiffs); } return(differences.ToArray()); }
public PropertyDifference[] GetCustomDifferences <T>(T firstObj, T secondObj) { Type type = typeof(T); if (!_customBuildersMap.ContainsKey(type)) { throw new KeyNotFoundException($"Для типа {type} не зарегистрирован builder"); } PropertiesTreeNode tree = _customBuildersMap[type].PropertyTree; return(GetDifferences(tree, firstObj, secondObj)); }
public PropertyDifference[] GetAutoDifferences <T>(T firstObj, T secondObj) { IAutoDifferenceSearchBuilder <T> searchBuilder = AutoBuilder <T>(); if (searchBuilder.PropertyTree == null) { searchBuilder.Build(); } PropertiesTreeNode tree = searchBuilder.PropertyTree; return(GetDifferences(tree, firstObj, secondObj)); }
private void DepthBuild(BuildTreeNode <AutoBuildTreeNodeConfig> buildNode, PropertiesTreeNode newNode) { PropertyInfo[] allTypeProperties = buildNode.PropertyType.GetProperties(); // Исключаем все игнорируемые поля. PropertyInfo[] neededProperties = allTypeProperties .Where(info => !buildNode.Config.IgnoredProperties.Contains(info.Name)).ToArray(); // Создаём другие node дерева. List <PropertiesTreeNode> newNodes = new List <PropertiesTreeNode>(); foreach (var info in neededProperties) { // Если в build версии дерева есть node, тогда проходим по его правилам. if (buildNode.ChildNodes.ContainsKey(info.Name)) { if (buildNode.ChildNodes[info.Name].Config.IsDeadEnd) { continue; } var newInnerNode = new PropertiesTreeNode(info); DepthBuild(buildNode.ChildNodes[info.Name], newInnerNode); newNodes.Add(newInnerNode); } // Если в build версии дерева нету node, тогда запускаем полностью рефлексивный обход. else if (!info.PropertyType.IsSimple()) { var newInnerNode = new PropertiesTreeNode(info); DifferenceSearchBuilderExtensions.AutoDepthBuild(info.PropertyType, newInnerNode); newNodes.Add(newInnerNode); } } newNode.InnerProperties = neededProperties; newNode.Nodes = newNodes.ToArray(); }
/// <summary> /// Запускает бесконтрольный рекурсивный билдер дерева. /// </summary> /// <param name="type">Тип текущей ветки дерева.</param> /// <param name="newNode">Ветка дерева.</param> /// <remarks> /// TODO Надо добавить Hashset<Type> чтобы отслеживать рекурсии и на них реагировать эксепшеном. /// </remarks> public static void AutoDepthBuild(Type type, PropertiesTreeNode newNode) { PropertyInfo[] allTypeProperties = type.GetProperties(); if (allTypeProperties.Any(x => x.PropertyType == type)) { throw new ArgumentException($"Property type matched class type. Stack overflow is inevitable. Type: '{type}'"); } List <PropertiesTreeNode> newNodes = new List <PropertiesTreeNode>(); foreach (var info in allTypeProperties) { if (!info.PropertyType.IsSimple()) { var newInnerNode = new PropertiesTreeNode(info); AutoDepthBuild(info.PropertyType, newInnerNode); newNodes.Add(newInnerNode); } } newNode.InnerProperties = allTypeProperties; newNode.Nodes = newNodes.ToArray(); }
public AutoDifferenceSearchBuilder() { PropertyTree = null; _buildRootNode = new BuildTreeNode <AutoBuildTreeNodeConfig>(typeof(TSource)); }