NancyFx DynamicDictionary
Я пытаюсь понять DynamicDictionary в NancyFX, это выглядит довольно круто. Кто-нибудь знает о блоге или аналогичном, который проходит через его внутренности?
Мне нужна сумка свойств для передачи объектов, содержимое которых я не знаю, потому что они приходят из-за пределов моей системы как JSON. Но исходя из содержимого этих объектов, таких как наличие определенных свойств, мне нужно что-то делать.
Я мог бы просто обойти динамические объекты, но это слишком размыто, я думаю. Не очень нравится.
Мне понадобятся вложенные словари, чтобы полностью представить граф объекта.
2 ответа
Динамический словарь - это просто ExpandoObject со словарем в нем. Таким образом, он все еще может быть доступен как словарь.
Например, в MVC вы получаете доступ к свойствам формы следующим образом:
var name = Request["name"];
или же
var name = Request.Form["name"];
Когда запрос поступает в Нэнси, вы можете получить к нему доступ через точечную запись. Или через индексатор классов.
var name = parameters.name;
var name = parameters["name"];
Это удобно, когда вы отправляете строку запроса или имя формы со значениями, которые нельзя использовать в точечной нотации.
var firstName = parameters["first-name"];
Значения также являются динамическими, поэтому они могут состоять из вложенных объектов. Это позволяет вам делать такие вещи, как:
var firstName = parameters.contact.firstname;
Поэтому, если вы передаете полезную нагрузку JSON в запрос, вы можете получить доступ ко всей структуре, используя точечную запись.
Однако вы, вероятно, найдете, что большинство разработчиков, использующих Nancy, когда-либо получают доступ к значениям Route или QueryString с помощью этого метода.
Get["/products/{id:int}/"] = parameters => {
int id = parameters.id;
};
Итак, вернемся к первоначальному вопросу:
Есть ли запись в блоге или любой документ: Нет.
Почему это существует: для синтаксиса сахара.
Могу ли я использовать это для того, что я хочу: Да, абсолютно!
Можете ли вы сказать мне, как его использовать: Нет, но это не должно быть сложно. Просто посмотрите модель привязки в Нэнси, чтобы понять это. Это не так уж сложно.
Просто редактирование на основе ответа ОП.
Когда вы получаете доступ к точечной нотации, продолжение точечной нотации будет работать только для дальнейших динамических типов.
Это означает использование var
вызовет исключение из-за способа var
а также dynamic
обрабатываются компилятором.
Когда вы делаете:
var person = parameters.person;
var name = person.name;
parameters
Сейчас dynamic
и реализует TryGetMember
это внутренне ищет словарь значений и пытается вернуть значение.
Когда вы определяете объект как var
для person
переменная. Компилятор предполагает, что что-либо после этого существует на объекте, поэтому он ищет name
на person
переменная.
поскольку name
не существует в качестве члена person
это бросит.
Чтобы решить эту проблему, переменная должна быть назначена как dynamic
, Итак, пример становится:
dynamic person = parameters.person;
var name = person.name;
Это будет работать
Поэтому я начал работать с DynamicDictionary, и с ним довольно круто и легко работать. Только одна вещь беспокоит меня прямо сейчас. Это если я вкладываю DynamicDictionaries.
Посмотрите на следующий пример:
private void TestNestedDynamicDictionary()
{
dynamic dictionary = new DynamicDictionary();
dynamic nestedDictionary = new DynamicDictionary();
nestedDictionary.Add("name", "Peter");
dictionary.Add("person", nestedDictionary);
var person = dictionary.person;
var name = person.name;
Console.WriteLine(name);
}
Это не удается при попытке доступа person.name
с 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
:
DynamicDictionaryValue' does not contain a definition for 'name'
Если я просто сделаю явное приведение, как это, это работает.
var person = (DynamicDictionary)dictionary.person;
Любые входные данные о том, как я могу заставить его вести себя как DynamicDictionary прямо из коробки... кроме проверки DynamicDictionaryValue до его возвращения и выполнения там приведения, что, на мой взгляд, является грязным.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object value;
if (!dictionary.TryGetValue(binder.Name, out value))
{
result = new DynamicDictionaryValue(null);
return true;
}
var dictVal = value as DynamicDictionaryValue;
if (null != dictVal && dictVal.Value is DynamicDictionary)
{
result = dictVal.Value;
}
else
{
result = value;
}
return true;
}