Цикл свойств DynamicObject

Я пытаюсь понять тип DynamicObject. Нашел эту статью MSDN очень краткой и ясной в отношении того, как создавать и использовать DynamicObject:

http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

В статье содержится простой класс DynamicDictionary, наследуемый от DynamicObject.

Теперь я хочу перебрать мои динамически созданные свойства DynamicObject:

dynamic d = new DynamicDictionary();
d.Name = "Myname";
d.Number = 1080;

foreach (var prop in d.GetType().GetProperties())
{
  Console.Write prop.Key;
  Console.Write prop.Value;
}

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

Нужна ли рефлексия? Я должен что-то упустить...


person joeriks    schedule 27.01.2011    source источник


Ответы (3)


Вы пробовали метод DynamicDictionary.GetDynamicMemberNames()? - http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.getdynamicmembernames.aspx

person Anuraj    schedule 27.01.2011
comment
Выглядит хорошо, но я не хочу/не могу изменить свой класс, а GetDynamicMemberNames() является необязательным, т.е. класс, наследуемый от DynamicObject, может переопределить его, если он хочет, но если это не так, вызывается функция в базовом классе, которая возвращает пустой список. - person joeriks; 27.01.2011
comment
Хм, я понимаю. Тогда я думаю, что либо вам нужно использовать ExpandoObject, либо вам нужно реализовать его самостоятельно. - person Anuraj; 27.01.2011

Я думаю, вас заинтересует класс ExpandoObject. . Класс DynamicObject — это просто база, в которой вы должны предоставить всю логику. Он явно реализует интерфейс IDictionary<string, object>, поэтому вы можете получить доступ к его свойствам или добавить новые таким образом.

// declare the ExpandoObject
dynamic expObj = new ExpandoObject();
expObj.Name = "MyName";
expObj.Number = 1000;

// print the dynamically added properties
foreach (KeyValuePair<string, object> kvp in expObj) // enumerating over it exposes the Properties and Values as a KeyValuePair
    Console.WriteLine("{0} = {1}", kvp.Key, kvp.Value);

// cast to an IDictionary<string, object>
IDictionary<string, object> expDict = expObj;

// add a new property via the dictionary reference
expDict["Foo"] = "Bar";

// verify it's been added on the original dynamic reference
Console.WriteLine(expObj.Foo);

Я только что понял, что вы реализуете класс DynamicDictionary, и неправильно понял ваш вопрос. Прости.

При использовании с динамической ссылкой у вас есть доступ только к общедоступным членам. Поскольку только Count объявлен общедоступным (помимо других членов DynamicObject), вам нужно будет использовать отражение, чтобы получить доступ к внутреннему словарю, чтобы легко получить эти значения (если вы не собираетесь вносить какие-либо дальнейшие изменения).

person Jeff Mercado    schedule 27.01.2011
comment
Хорошо, спасибо, так что - для существующего объекта, который наследует DynamicObject и не предоставляет словарь - у меня нет способа (кроме использования Reflection) получить словарь членов? - person joeriks; 27.01.2011
comment
АФАИК да. Вы можете получить доступ только к общедоступным членам и классу DynamicObject, где доступ к членам разрешается с помощью различных методов. В качестве альтернативы вы можете явно реализовать класс IDictionary<string, object> точно так же, как ExpandoObject, чтобы упростить этот процесс. - person Jeff Mercado; 27.01.2011
comment
p.s. Извините, что сначала упустил ваш вопрос. Я не заметил, что вы на самом деле реализовывали код примера. Я думал про себя, DynamicDictionary класса нет... :) - person Jeff Mercado; 27.01.2011
comment
Часть ответа, которая не отвечает на вопрос, - это именно то, что я искал. - person Bovaz; 22.09.2016

Я знаю, что эта тема довольно старая, но для тех, кто все еще задается вопросом, как это сделать, почему бы не использовать метод TryGetMember(), а создать класс, который наследует GetMemberBinder, например:

public class MyGetMemberBinder : GetMemberBinder
{
    public MyGetMemberBinder(string name, bool ignorecase) : base(name, ignorecase) { }
    public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)=>throw new NotImplementedException();
}

Затем с помощью LINQ:

Dictionary<string, object> AsStandardDictionary = DynamicDictionary.GetDynamicMemberNames().ToDictionary(x => x, y =>
{
    if(DynamicDictionary.TryGetMember(new MyGetMemberBinder(y, false), out var result))
        return result;
    else
        return null;
});
person IRLotsEvil    schedule 07.07.2020