我有一些将强类型业务对象映射到匿名类型的代码,然后将其序列化为
JSON并通过API公开.
在将我的解决方案重组为单独的项目后,我的一些测试开始失败.我已经做了一些挖掘,事实证明,Object.Equals在匿名类型上的行为有所不同,这些类型由不同程序集的代码返回 – 我不知道为什么,或者我可以做些什么来解决它.
在https://github.com/dylanbeattie/AnonymousTypeEquality有完整的可用代码,但实际打破的位在下面.此代码位于Tests项目中:
[TestFixture] public class Tests { [Test] public void BothInline() { var a = new { name = "test",value = 123 }; var b = new { name = "test",value = 123 }; Assert.That(Object.Equals(a,b)); // passes } [Test] public void FromLocalMethod() { var a = new { name = "test",value = 123 }; var b = MakeObject("test",123); Assert.That(Object.Equals(a,b)); // passes } [Test] public void FromOtherNamespace() { var a = new { name = "test",value = 123 }; var b = OtherNamespaceClass.MakeObject("test",b)); // passes } [Test] public void FromOtherClass() { var a = new { name = "test",value = 123 }; var b = OtherClass.MakeObject("test",123); /* This is the test that fails,and I cannot work out why */ Assert.That(Object.Equals(a,b)); } private object MakeObject(string name,int value) { return new { name,value }; } }
namespace OtherClasses { public static class OtherClass { public static object MakeObject(string name,int value) { return new { name,value }; } } }
根据MSDN年,“同一个匿名类型的两个实例只有在所有属性相等的情况下才是平等的”. (我的重点) – 所以控制两个实例是否是相同的匿名类型进行比较?我的两个实例具有相等的哈希码,并且两者似乎都是<> f_AnonymousType0`2 [System.String,System.Int32] – 但是我猜测匿名类型的相等性必须考虑到完全限定的类型名称,因此将代码移入不同的程序集可能会破坏事物.任何人得到一个明确的来源/链接,这是如何实现的?
解决方法
如果您使用Reflector这样的工具反汇编您的程序集,您将看到您的匿名类型由每个程序集中的一个类代表,看起来像这样(在解压缩编译器生成的标识符之后):
internal sealed class AnonymousType<TName,TValue> { private readonly TName _name; private readonly TValue _value; public TName name => this._name; public TValue value => this._value; public AnonymousType(TName name,TValue value) { this._name = name; this._value = value; } public override bool Equals(object value) { var that = value as AnonymousType<TName,TValue>; return that != null && EqualityComparer<TName>.Default.Equals(this._name,that._name) && EqualityComparer<TValue>.Default.Equals(this._value,that._value); } public override int GetHashCode() { // ... } }
Equals方法的第一行检查值是否是AnonymousType< TName,TValue的实例,具体涉及当前程序集中定义的类.因此,来自不同程序集的匿名类型将永远不会相等,即使它们具有相同的结构. 您可能需要更改测试以比较对象的序列化JSON而不是对象本身.