Вопрос по dynamic, c# – Отличный ответ - но мой вопрос вводил в заблуждение. Я пытался сравнить с динамическими объектами. Тот факт, что они были ExpandoObject, был просто моим примером создания динамического объекта. Произвольные динамические объекты, кажется, не выставляют счетчики, как ответил Раймонд

13

наилучший способ сравнить два произвольных динамических объекта на равенство? Например, эти два объекта.

То есть

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 из динамического типа?

Хммм - я думаю, что смотрел на это неправильно. Возможно, мне придется создать класс для моего объекта и наследовать от DynamicObject (msdn.microsoft.com/en-us/library/...). Тогда я могу использовать методы, такие как GetDynamicMemberNames (msdn.microsoft.com/en-us/library/...) и TryGetMember (msdn.microsoft.com/en-us/library/...) запрашивать и сравнивать объекты. Marcus Hammarberg

Ваш Ответ

5   ответов
9

ных динамических объектов (IDynamicMetaObjectProvider) нелегко использовать, если у вас нет помощи компилятора. Вы можете использоватьDynamitey (через Nuget), чтобы упростить это полностью. Имеет статическую функциюDynamic.InvokeGet называть получатели свойства только с целью и именем свойства.

Чтобы получить список свойств динамического объекта, есть небольшая хитрость, поскольку динамический объект должен его поддерживать (если это DynamicObject, который означает реализацию GetDynamicMemberNames, Expando поддерживает его, но случайный IDynamicMetaObjectProvider может и не возвращать просто пустой список). У Dynamitey есть метод упрощения получения этих имен,Dynamic.GetMemberNames.

Обе эти две функции дают вам базовые инструменты, необходимые для сравнения множества произвольных динамических объектов через свойства.

//using System.Dynamic;
//using Dynamitey;
//using System.Linq;

IEnumerable<string> list1 =Dynamic.GetMemberNames(obj1);
list1 = list1.OrderBy(m=>m);
IEnumerable<string> 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;

Однако, если они являются только вашим собственным подклассом DynamicObject, было бы легче просто следоватьправила реализации РавныхНа самом деле нет никаких отличий от нединамических объектов, и просто сравните то, что вы используете для состояния.

Чувак - это прекрасно сработало! Смотрите мое использование здесь:github.com/marcushammarberg/SpecFlow.Assist.Dynamic , Именно то, что я искал. Спасибо Marcus Hammarberg
Whooa - это выглядит великолепно. Я проверю это для моего использования и свяжусь с вами Marcus Hammarberg
1

IDictonary<string, object> так что вы должны быть в состоянии использовать это.

Что-то вроде

Assert.AreEqual((IDictonary(object, string))obj1, (IDictonary(object, string))obj2); 

редактировать AreEqual не сработает

Но вы можете попробовать сравнить два словаря довольно просто.

Отличный ответ - но мой вопрос вводил в заблуждение. Я пытался сравнить с динамическими объектами. Тот факт, что они были ExpandoObject, был просто моим примером создания динамического объекта. Произвольные динамические объекты, кажется, не выставляют счетчики, как ответил Раймонд Marcus Hammarberg
1

чтобы получить членов ExpandoObject.http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx

Произвольные динамические объекты, по-видимому, не выставляют счетчики.

Спасибо - мой вопрос не был правильно задан, но вы его получили. Я спрашивал о произвольных динамических объектах. Marcus Hammarberg
1

IComparable-Интерфейс. Затем у вас есть соответствующие функции, необходимые из .NET / C # для сравнения двух объектов друг с другом.

Отличный ответ - но мой вопрос вводил в заблуждение. Я пытался сравнить с динамическими объектами. Тот факт, что они были ExpandoObject, был просто моим примером создания динамического объекта. Произвольные динамические объекты не могут сделать это, как ответил Раймонд Marcus Hammarberg
10

ExpandoObject инвентарьICollection<KeyValuePair<string, object>> (в дополнении кIDictionary а такжеIEnumerable то же самое), так что вы должны быть в состоянии сравнить их свойство по свойству довольно легко:

 ExpandoObject obj2)
{
    var obj1AsColl = (ICollection<KeyValuePair<string,object>>)obj1;
    var obj2AsDict = (IDictionary<string,object>)obj2;

    // Make sure they have the same number of properties
    if (obj1AsColl.Count != obj2AsDict.Count)
        return false;

    foreach (var pair in obj1AsColl)
    {
        // Try to get the same-named property from obj2
        object o;
        if (!obj2AsDict.TryGetValue(pair.Key, out o))
            return false;

        // Property names match, what about the values they store?
        if (!object.Equals(o, pair.Value))
            return false;
    }

    // Everything matches
    return true;
}
Отличный ответ - но мой вопрос вводил в заблуждение. Я пытался сравнить с динамическими объектами. Тот факт, что они были ExpandoObject, был просто моим примером создания динамического объекта. Произвольные динамические объекты, кажется, не выставляют счетчики, как ответил Раймонд. Marcus Hammarberg

Похожие вопросы