C# 获取对象结构差异和统计信息的模式,或如何创建差异工具
假设我有这样的结构C# 获取对象结构差异和统计信息的模式,或如何创建差异工具,c#,algorithm,design-patterns,data-structures,comparison,C#,Algorithm,Design Patterns,Data Structures,Comparison,假设我有这样的结构 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
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
}
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
}
字段
基本上是复合结构,每个字段
包含子字段列表。因此,结构是分层的。字段还引用了字段类型
类
public class FieldType
{
#region Public Properties
public DataType DataType { get; set; }
public string DisplayName { get; set; }
public string Id { get; set; }
#endregion
}
最后我们参考了数据类型
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
}
和差异类
public struct Difference
{
public readonly string Property;
public readonly DifferenceType Type;
public readonly IExtractionable Expected;
public readonly IExtractionable Actual;
}
但这可能不是我想要的方式,因为我应该更精确地比较字段,考虑到每个字段都有Id,对于不同的形式,Id也可能不同,我想对比较过程进行更多的控制。对我来说,这听起来更像是一个差异工具
因此,我正在寻找良好的模式和良好的结构,以便将差异发布到客户端代码中,这样可以很容易地将其可视化?鉴于您的类已经非常有名,我将使用以下内容:
- 一个IDiffable接口,使类具有DiffWith(T other)类,返回差异枚举。因此,在每个类中实现DiffWith是有意义的,考虑到它们基本上是固定的,这应该很简单
- 一个单独的ReflectionDiff(可能是静态的)类,它将以使用反射的方式进行比较。这一个可以使用属性来白名单/忽略任何属性/字段。这样,您就可以有一个默认的diff引擎来快速实现差异,并完全使用您正在使用的反射代码。您可以简单地通过以下方式实现diff:
public override IEnumerable<Difference> DiffWith(Field other)
{
return ReflectionDiff.Diff(this, other);
}
public override IEnumerable DiffWith(字段其他)
{
返回ReflectionDiff.Diff(此,其他);
}
您可以得到一个包含所有脏反射代码的类(实际上并不需要),并且可以在每个可扩散类中实现一个简单的DiffWith。不确定您所追求的解决方案有多优雅,但如果您只是想要一个具有最少编码的快速解决方案,那么可能:
序列化要与文本格式进行比较的实例(例如使用JSON.NET的JSON)
将序列化对象写入文本文件
启动一个diff工具,将这两个文本文件作为参数传递(像ExamDiff这样的工具很容易做到这一点)
正如我所说,这是一个快速的解决方案,但可能足以满足您的需要。另外,还有一些命令行diff工具可供使用,它们将输出一个unix风格的diff文件,然后您可以为该文件编写自己的可视化工具。在研究了一点并比较了不同的资源之后,我实现了这种算法
获取对象并构造图形(使用.GetType().GetProperties(),将每个属性添加为根节点的子节点。节点的键将是属性名称
如果遇到任何自定义类型或IEnumerable的属性,请递归执行
创建图形比较器并简单比较两个图形
稍后,我将发布我的代码并更新答案。为什么您首先决定使用reflection int?您的类是已知的强类型。您是否也计划在其他类上使用它?也许这个问题与您的相关:尽管给出的答案很有用,但我强烈建议您看看第二个答案swer指出,它有一个“深度对象比较API”,如第8部分所述。嗯,不是真的,现在没有其他类。其想法是创建灵活的解决方案,以后也可以使用它来比较其他类,所以我先尝试反射。
public override IEnumerable<Difference> DiffWith(Field other)
{
return ReflectionDiff.Diff(this, other);
}