比较 C# 中的动态对象
比较两个任意动态对象是否相等的最佳方法是什么?例如这两个对象。
即
dynamic obj1 = new ExpandoObject();
obj1.Name = "Marcus";
obj1.Age = 39;
obj1.LengthInMeters = 1.96;
dynamic obj2 = AMethodReturningADynamic();
obj2.Name = "Marcus";
obj2.Age = 39;
obj2.LengthInMeters = 1.96;
Assert.AreEqual(obj1, obj2); // ?
或者有没有办法以列表的形式获取实际属性及其值?例如,要从动态类型创建 ExpandoObject?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
当您没有编译器的帮助时,用于动态调用任意动态对象 (IDynamicMetaObjectProvider) 上的方法和属性的 Microsoft API 并不容易使用。您可以使用 Dynamitey (通过 nuget)来完全简化此操作。它有一个静态函数 Dynamic.InvokeGet 来仅使用目标和属性名称来调用属性的 getter。
要获取动态对象的属性列表,有一些陷阱,因为动态对象必须支持它(如果它是一个 DynamicObject,意味着实现 GetDynamicMemberNames,Expando 支持它,但随机 IDynamicMetaObjectProvider 可能不支持它,只返回一个空列表)。 Dynamitey 也有一种简化获取这些名称的方法, 动态.GetMemberNames。
这两个函数都为您提供了通过属性比较许多任意动态对象所需的基本工具。
但是,如果它们只是您自己的 DynamicObject 子类,那么遵循典型的 实现 Equals 的规则,与非动态对象确实没有区别,只需比较您内部使用的状态即可。
The Microsoft API's for dynamically invoking methods and propertys on arbitrary dynamic objects (IDynamicMetaObjectProvider) are not easy to use when you don't have the compiler's help. You can use Dynamitey (via nuget) to simplify this completely. It has a static function Dynamic.InvokeGet to call property's getters with just a target and a property name.
To get a list of properties of the dynamic object, there is a bit of a gotcha, as the dynamic object has to support it (if it's a DynamicObject that means implementing GetDynamicMemberNames, Expando supports it, but random IDynamicMetaObjectProvider may not and just return an empty list). Dynamitey has a method to simplifying getting those names as well, Dynamic.GetMemberNames.
Both of those two functions give you the basic tools necessary to compare many arbitrary dynamic objects via properties.
However, if they are just your own DynamicObject subclass then it'd be easier to just follow the typical rules for implementing Equals, there really is no difference from non-dynamic objects, and just compare what you are internally using for state.
ExpandoObject
实现ICollection>
(除了相同的IDictionary
和IEnumerable
),所以你应该能够很容易地比较它们的属性:ExpandoObject
implementsICollection<KeyValuePair<string, object>>
(in addition toIDictionary
andIEnumerable
of the same), so you should be able to compare them property by property pretty easily:请参阅“枚举和删除成员”以获取 ExpandoObject 的成员 http 不过,://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
任意动态对象似乎不会公开枚举器。
See "Enumerating and deleting members" to get the members of an ExpandoObject http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
Arbitrary dynamic objects do not appear to expose enumerators, though.
您必须实施 IComparable -界面。然后,您就可以使用 .NET/C# 中所需的适当函数来相互比较两个对象。
You have to implement IComparable-Interface. Then you have the appropriate functions needed from .NET/C# to compare two objects with each other.
您还可以使用 GitHub 上提供的 ObjectsComparer 库:
ObjectsComparer
这个库是一个对象到对象比较器,允许我们逐个成员递归地比较对象,并且为某些属性、字段或类型定义自定义比较规则。它支持枚举(数组、集合、列表)、多维数组、枚举、标志和动态对象(ExpandoObject、DynamicObject 和编译器生成的动态对象)。
转到 Valerii Tereshchenko 优秀的论文提供了更多细节。
You can also use the ObjectsComparer library available on GitHub :
ObjectsComparer
This library is an object-to-object comparer that allows us to compare objects recursively member by member and to define custom comparison rules for certain properties, fields or types. It supports enumerables (arrays, collections, lists), multidimensional arrays, enumerations, flags and dynamic objects (ExpandoObject, DynamicObject and compiler generated dynamic objects).
Go to Valerii Tereshchenko excellent paper for more details.
Expando 对象可用作
IDictonary
因此您应该能够使用它。像
编辑
AreEqual
这样的东西将不起作用。但您可以尝试相当简单地比较这两个词典。
Expando Objects are useable as an
IDictonary<string, object>
so you should be able to use that.Something like
Edit the
AreEqual
won't work.But you could try comparing the two dictionaries fairly simply.