假设我有这样的结构
public class Form
{
#region Public Properties
public List<Field> Fields { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public string Version { get; set; }
public int Revision { get; set; }
#endregion
}
所以Form
类包含字段列表,假设字段本身是用这种结构表示的
public class Field
{
#region Public Properties
public string DisplayName { get; set; }
public List<Field> Fields { get; set; }
public string Id { get; set; }
public FieldKind Type { get; set; }
public FieldType FieldType { get; set; }
#endregion
}
Field
基本上是复合结构,每个都包含Field
子字段列表。所以结构是分层的。Field 也引用了FieldType
该类。
public class FieldType
{
#region Public Properties
public DataType DataType { get; set; }
public string DisplayName { get; set; }
public string Id { get; set; }
#endregion
}
最后我们参考了DataType
public class DataType
{
#region Public Properties
public string BaseType { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public List<Restriction> Restrictions { get; set; }
#endregion
}
我想要实现的是获得这种复杂结构的差异,比方说,如果我有某种比较器,它将给我作为一个类的整个表单的结构化差异,比如说差异结果。当我说结构化差异时,我的意思是它应该是这样的。
- 字段差异
Form
(输出Form
在版本字段中有差异(不同颜色) - 集合的差异
Fields
,包括字段与已编辑字段的层次结构 FieldType
和的行为相同DataType
- 检测删除和添加
Field
到Form
(所以可能每个差异都会有一个类型)
我现在拥有的。我从通用方法开始,并尝试使用 ReflectionComparer 实现 IEqualityComparer 接口
public bool Equals(T x, T y)
{
var type = typeof(T);
if (typeof(IEquatable<T>).IsAssignableFrom(type))
{
return EqualityComparer<T>.Default.Equals(x, y);
}
var enumerableType = type.GetInterface(typeof(IEnumerable<>).FullName);
if (enumerableType != null)
{
var elementType = enumerableType.GetGenericArguments()[0];
var elementComparerType = typeof(DifferenceComparer<>).MakeGenericType(elementType);
var elementComparer = Activator.CreateInstance(elementComparerType, new object[] { _foundDifferenceCallback, _existedDifference });
return (bool)typeof(Enumerable).GetGenericMethod("SequenceEqual", new[] { typeof(IEnumerable<>), typeof(IEnumerable<>), typeof(IEqualityComparer<>) }).MakeGenericMethod(elementType).Invoke(null, new[] { x, y, elementComparer });
}
foreach (var propertyInfo in type.GetProperties())
{
var leftValue = propertyInfo.GetValue(x);
var rightValue = propertyInfo.GetValue(y);
if (leftValue != null)
{
var propertyComparerType = typeof(DifferenceComparer<>).MakeGenericType(propertyInfo.PropertyType);
var propertyComparer = Activator.CreateInstance(propertyComparerType, new object[] {_foundDifferenceCallback, _existedDifference});
if (!((bool)typeof(IEqualityComparer<>).MakeGenericType(propertyInfo.PropertyType)
.GetMethod("Equals")
.Invoke(propertyComparer, new object[] { leftValue, rightValue })))
{
// Create and publish the difference with its Type
}
}
else
{
if (!Equals(leftValue, rightValue))
{
// Create and publish the difference with its Type
}
}
}
//return true if no differences are found
}
和Difference
类
public struct Difference
{
public readonly string Property;
public readonly DifferenceType Type;
public readonly IExtractionable Expected;
public readonly IExtractionable Actual;
}
但可能这不是我想要的方式,因为我应该更精确地比较 Field,考虑到每个 Field 都有 Id,对于不同的形式也可能不同,我想更好地控制比较过程。对我来说,这听起来更像是一个差异工具。
所以我正在寻找好的模式和相当好的结构来将差异发布到客户端代码,这可以很容易地可视化它?