В хелпер asp.net я передаю переменную htmlAttributes вида:
new { @class = "btn btn-default", title = "classic view" };
При этом внутри хелпера мне иногда нужно добавить css класс active при выполнении некоторого условия:
new { @class = "btn btn-default active", title = "classic view" };
Как это сделать проще всего?
Сам я попробовал полезть через рефлексию
foreach (var i in htmlAttributes.GetType().GetProperties())
{
Console.Write(i.GetValue(a));
}
, но вспомнил, что анонимные типы - только для чтения, они вообще без setter'ов создаются.
Можно ли создать копию, с немного другими значениями?
Тут все зависит от того что потребитель будет делать с этим объектом. Для передачи в хелперы Razor проще всего преобразовать объект в RouteValueDictionary и дальше использовать другую перегрузку:
var dict = new RouteValueDictionary(obj);
dict["class"] += " active";
Также можно "обмануть" потребителя передав ему объект реализующий ICustomTypeDescriptor
- многие потребители, и Razor в их числе, используют именно ComponentModel вместо рефлексии для получения свойств объекта.
Если же объект предполагается передавать в интерпретируемые языки использующие DLR - то можно использовать ExpandoObject:
var dict = (IDictionary<string, object>)new ExpandoObject();
foreach (var pair in new RouteValueDictionary(obj))
dict.Add(pair);
dynamic foo = dict;
foo.@class += " active";
Ну а если требуется точное совпадение типа - ничего не поделать, придется использовать вариант Андрея и надеяться что разработчики компилятора не поменяют особенности реализации...
Просто создадим новый объект через рефлексию, передавая массив значений в конструктор:
static object CreateModified(object obj, string propName, object newValue)
{
var type = obj.GetType();
var props = type.GetProperties();
var values = props.Select(p => p.Name == propName ? newValue : p.GetValue(obj)).ToArray();
return Activator.CreateInstance(type, values);
}
Решение довольно хрупкое, полагается на то, что в текущей реализации компилятора свойства в анонимном классе создаются в том же порядке, что и параметры его конструктора.
Используем:
var a = new { @class = "btn btn-default", title = "classic view" };
Console.WriteLine(a);
var b = CreateModified(a, "class", a.@class + " active");
Console.WriteLine(b);
Вроде работает, но делать я так бы не стал.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Требуется пройти по DataGridView и найти там определенные данные, введенные с textboxКак это реализовать?