Comparing dynamic objects in C#

前端 未结 6 2303
不知归路
不知归路 2021-02-13 04:08

What is the best way to compare two arbitrary dynamic objects for equality? For example these two objects.

I.e.

dynamic obj1 = new ExpandoObject();
obj1.         


        
6条回答
  •  生来不讨喜
    2021-02-13 04:32

    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.

    //using System.Dynamic;
    //using Dynamitey;
    //using System.Linq;
    
    IEnumerable list1 =Dynamic.GetMemberNames(obj1);
    list1 = list1.OrderBy(m=>m);
    IEnumerable list2 =Dynamic.GetMemberNames(obj2);
    list2 = list2.OrderBy(m=>m);
    
    if(!list1.SequenceEqual(list2))
     return false;
    
    foreach(var memberName in list1){
     if(!Dynamic.InvokeGet(obj1, memberName).Equals(Dynamic.InvokeGet(obj2,memberName))){
        return false;
     }
    }
    return true;
    

    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.

提交回复
热议问题