Можно ли объявить анонимный тип в C # с переменным / динамическим набором полей?

anonymous-types c# dapper dynamic

Вопрос

В C # я хотел бы выяснить, можно ли объявить анонимный тип, где поля не известны до времени выполнения.

Например, если у меня есть пара ключей / значений, могу ли я объявить анонимный тип на основе содержимого этого списка? В конкретном случае, с которым я работаю, передаются параметры Dapper, где я заранее не знаю, сколько параметров у меня будет.

List<Tuple<string, string>> paramList = new List<Tuple<string, string>>() {
    new Tuple<string, string>("key1", "value1"),
    new Tuple<string, string>("key2", "value2")
    ...
};

Я хотел бы преобразовать этот список (или эквивалентную карту) в анонимный тип, который я могу передать Dapper в качестве параметров запроса. Поэтому в идеале приведенный выше список будет выглядеть так, если он определен как анонимный тип:

new { key1=value1, key2=value2, ... }

Я видел несколько вопросов о StackOverflow о расширении анонимных типов после их объявления («объекты-объекты») или объявлении произвольных полей объекта после его создания, но мне не нужно это делать ... Мне просто нужно однократно объявлять типы динамически. Мое подозрение в том, что для этого потребуется какое-то причудливое отражение, если это вообще возможно.

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

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

Благодаря!

ОБНОВИТЬ

Извините за задержку в возвращении к этому! Эти ответы были прекрасными, мне хотелось бы дать оценку всем. Я закончил использование решения jbtule (с разрешением Сэма Шаффрона), передав IDynamicParameters в Dapper, поэтому я почувствовал, что должен дать ему ответ. Другие ответы были хорошими, и я ответил на конкретные вопросы, которые я задал. Я очень ценю, что все время на это!

Принятый ответ

Создатели Даппера очень хорошо понимали эту проблему. Эта функциональность действительно необходима для помощников INSERT и UPDATE .

Методы Query , Execute и QueryMultiple принимают dynamic параметр. Это может быть анонимный тип, конкретный тип или объект, который реализует IDynamicParameters .

public interface IDynamicParameters
{
    void AddParameters(IDbCommand command, Identity identity);
}

Этот интерфейс очень удобен, AddParameters вызывается непосредственно перед запуском любого SQL. Это не только дает вам богатый контроль над параметрами, отправленными на SQL. Это позволяет вам подключать DB DarParameters, поскольку у вас есть доступ к команде (вы можете отнести ее к определенному db). Это позволяет поддерживать параметры табличных значений и т. Д.

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

Вы можете использовать метод AddDynamicParams для добавления анонимного типа.

var p = new DynamicParameters();
p.AddDynamicParams(new{a = "1"});
p.AddDynamicParams(new{b = "2", c = "3"});
p.Add("d", "4")
var r = cnn.Query("select @a a, @b b, @c c, @d d", p);
// r.a == 1, r.b == 2, r.c == 3, r.d == 4

Популярные ответы

В C # я хотел бы выяснить, можно ли объявить анонимный тип, где поля не известны до времени выполнения.

Анонимные типы генерируются компилятором. Вы хотите знать, генерирует ли компилятор вас генерируемый компилятором тип с типами полей, которые не известны компилятору . Ясно, что он не может этого сделать; как вы правильно догадались, вам не повезло.

Я видел несколько вопросов о StackOverflow о том, как расширить анонимные типы после их объявления («объекты-объекты»)

Обычно мы называем эти объекты «expando».

Если то, что вы хотите сделать, это сделать объект expando на основе словаря пар ключ-значение, а затем использовать класс ExpandoObject для этого. Подробнее см. В статье MSDN:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

Если то, что вы хотите сделать, это генерировать bona-fide .NET-класс во время выполнения, вы тоже можете это сделать. Как вы правильно заметили, вам нужно какое-то причудливое размышление. То, что вы хотите сделать, это сделать сборную сборку (так называемую, потому что, в отличие от обычной сборки, вы создаете ее во время выполнения, и сборщик мусора очистит ее, когда вы закончите с ней).

См. Http://msdn.microsoft.com/en-us/library/dd554932.aspx для получения подробных сведений о том, как сделать сборную сборку и испускать в нее тип с помощью TypeBuilder.



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему