2

另请参阅如何快速检查数据传输两个对象在 C# 中是否具有相同的属性?

我有很多数据传输对象 (DTO),每个都包含很多简单的字段。我需要在所有这些上实现 Equals(所以我可以编写一些单元测试来传输它们 var WCF)。

我正在使用的代码是:

public override bool Equals(object rhs)
{

    RequestArguments other = rhs as RequestArguments;

    return
       other != null && 
       other.m_RequestId.Equals(RequestId) && 
       other.m_Type.Equals(m_Type) && 
       other.m_Parameters.Equals(m_Parameters) && 
       other.m_user.Equals(m_user);
}

一定有更好的方法!... (列出所有字段是宁愿要求错误和维护问题)

例如我们有对象。MemberwiseClone() 可以帮助解决 Cloning() 案例,但我找不到任何可以帮助解决 Equals 的问题。我们在完全信任的情况下运行,因此基于反射的解决方案是一个答案,但我宁愿不重新发明轮子。

(抱歉,我们没有从特定领域的语言生成 DTO,否则这种事情会很容易!而且我无法更改构建系统以添加另一个步骤)

4

4 回答 4

3

有趣的是你应该问,我最近发布了一些代码来做到这一点。查看我的MemberwiseEqualityComparer,看看它是否符合您的需求。

它真的很容易使用而且效率也很高。它使用 IL-emit 在第一次运行时生成整个 Equals 和 GetHashCode 函数(每种类型使用一次)。它将使用该类型的默认相等比较器 (EqualityComparer.Default) 比较给定对象的每个字段(私有或公共)。我们已经在生产中使用它一段时间了,它看起来很稳定,但我不能保证 =)

它处理了所有那些你在滚动自己的 equals 方法时很少想到的那些讨厌的边缘情况(即,你不能将自己的对象与 null 进行比较,除非你首先将它装箱到一个对象中并且很多都关闭了更多与 null 相关的问题)。

我一直想写一篇关于它的博客文章,但还没有开始。代码有点无证,但如果你喜欢它,我可以清理一下。

public override int GetHashCode()
{
    return MemberwiseEqualityComparer<Foo>.Default.GetHashCode(this);
}

public override bool Equals(object obj)
{
    if (obj == null)
        return false;

    return Equals(obj as Foo);
}

public override bool Equals(Foo other)
{
    return MemberwiseEqualityComparer<Foo>.Default.Equals(this, other);
}

MemberwiseEqualityComparer 是在MIT 许可下发布的,这意味着您几乎可以用它做任何您想做的事情,包括在专有解决方案中使用它而无需更改您的许可。

于 2009-12-02T09:50:01.050 回答
1

一种选择是使用反射来获取所有可用字段,然后在所需对象上获取并比较它们的值。这将为您提供一个通用的解决方案,但您需要做很多工作,可能像 Alex 建议的那样使用哈希是一种更清洁的解决方案。

编辑:这是一个使用反射比较对象的简单示例,它查看属性而不是字段,但您明白了: http: //www.willasrari.com/blog/use-systemreflection-for-comparing-custom-objects/ 000257.aspx

于 2009-12-02T09:40:01.353 回答
0

你可以有一个对象散列的概念——每当一个对象发生变化时,你都要为更新散列付出代价(其中散列实际上是所有连接属性的散列)。然后,如果您有一堆很少更改的对象,那么比较它们真的很便宜。当然,价格是在对象编辑时支付的。

于 2009-12-02T09:35:46.573 回答
0

编辑:抱歉,我没有注意到您要求进行序列化测试。所以这种方法绝对不适合你。


还有另一种“肮脏”的方式。如果您的对象无论如何都是可序列化的,您可以序列化它们并比较结果流。

这相当慢,但应该非常可靠且易于实现。

我们有时这样做是为了检查是否有人更改了编辑器中的任何数据。

于 2009-12-02T09:44:06.620 回答