将子类实例的基类部分与另一个基类实例进行比较

时间:2010-04-06 13:29:04

标签: c#

我在系统中有多个DTO类。它们以继承层次结构组织。

class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string ListName { get; set; }
}

class PersonDetailed : Person
{
    public string WorkPhone { get; set; }
    public string HomePhone { get; set; }
    public byte[] Image { get; set; }
}

将其拆分的原因是为了能够获得例如人的列表。搜索结果,无需拖动沉重的图像和电话号码。然后,当选择一个人的详细信息时,将加载完整的PersonDetail DTO。

我遇到的问题是在编写单元测试时比较这些问题。假设我有

Person p1 = myService.GetAPerson();
PersonDetailed p2 = myService.GetAPersonDetailed();

// How do I compare the base class part of p2 to p1?
Assert.AreEqual(p1, p2);

上面的Assert会失败,因为p1p2是不同的类。是否有可能只是将p2的基类部分与p1进行比较?我应该在IEquatable<>上实施Person吗?其他建议?

2 个答案:

答案 0 :(得分:2)

我相信Assert.AreEqual会在所涉及的实例上调用Equals方法。您应该能够简单地覆盖Equals逻辑并检查运行时是否正在比较其中一种可能的情况:

  • 人&lt; - &gt;人
  • 人&lt; - &gt; PersonDetailed
  • PersonDetailed&lt; - &gt;人或
  • PersonDetailed&lt; - &gt; PersonDetailed

您可以为每种情况实施适当的逻辑,或者根据需要委托给外部比较器。如果除了微软之外的任何单元测试框架支持检查IEquatable<T>,当你要求它们验证相等时,我都不知道。

答案 1 :(得分:0)

更多的调查(根据LBushkin的回答)让我改变主意。

Assert.Equals调用Equals方法来比较对象。在我的情况下,我可以在Person上创建一个覆盖,它将接受任何可以转换为Person的类型,然后比较所有属性。这将使我的原始代码工作:

Assert.AreEqual(p1, p2);

我还必须在我的PersonExtended类中重写Equals以检查存在的额外字段。然而,这将产生“有趣”的后果:

Assert.AreEqual(p1, p2); // calls p1.Equals(p2) - evaluates to true.
Assert.AreEqual(p2, p1); // calls p2.Equals(p1) - evaluates to false.

此时我决定构建更简单的东西 - 结果是Person类型的扩展方法进行比较。这有一些优点:

  • 可以处理null左手参数。
  • 它是非虚拟的 - 很明显变量的声明类型是比较 使用。

现在一切似乎都很好,我可以继续编码。直到我发现在基本DTO和扩展DTO之间继承的整个想法是有缺陷的。我认为WCF使用的DataContractSerializer将序列化声明函数参数的类型。它没有。它序列化对象的实际类型。这意味着如果将一个PersonExtended对象传递给只需要Person的方法,则无论如何都会通过线路传输整个扩展方法,因此最好坚持使用简单的合成。