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;
}
Другие вопросы по тегам