Добавить свойство к анонимному типу после создания

101

Я использую анонимный объект для передачи моих атрибутов Html некоторым вспомогательным методам. Если потребитель не добавил атрибут ID, я хочу добавить его в свой вспомогательный метод.

Как я могу добавить атрибут к этому анонимному объекту?

Борис Калленс
источник

Ответы:

17

Если вы пытаетесь расширить этот метод:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues);

Хотя я уверен, что расширения объекта Khaja будут работать, вы можете повысить производительность, создав RouteValueDictionary и передав объект routeValues, добавив дополнительные параметры из контекста, а затем вернувшись с помощью перегрузки ActionLink, которая принимает RouteValueDictionary вместо объекта:

Это должно помочь:

    public static MvcHtmlString MyLink(this HtmlHelper helper, string linkText, string actionName, object routeValues)
    {
        RouteValueDictionary routeValueDictionary = new RouteValueDictionary(routeValues);

        // Add more parameters
        foreach (string parameter in helper.ViewContext.RequestContext.HttpContext.Request.QueryString.AllKeys)
        {
            routeValueDictionary.Add(parameter, helper.ViewContext.RequestContext.HttpContext.Request.QueryString[parameter]);
        }

        return helper.ActionLink(linkText, actionName, routeValueDictionary);
    }
Левитикон
источник
Работает как шарм, это должен быть принятый ответ! Кстати: если вы до сих пор используете объектные перегрузки ActionLink (), вам нужно обернуть htmlAttributes с помощью HtmlHelper.AnonymousObjectToHtmlAttributes (htmlAttributes), чтобы вызвать правильную перегрузку!
DR
79

Следующий класс расширения даст вам то, что вам нужно.

public static class ObjectExtensions
{
    public static IDictionary<string, object> AddProperty(this object obj, string name, object value)
    {
        var dictionary = obj.ToDictionary();
        dictionary.Add(name, value);
        return dictionary;
    }

    // helper
    public static IDictionary<string, object> ToDictionary(this object obj)
    {
        IDictionary<string, object> result = new Dictionary<string, object>();
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(obj);
        foreach (PropertyDescriptor property in properties){
            result.Add(property.Name, property.GetValue(obj));
        }
        return result;
    }
}
Хаджа Минхаджуддин
источник
4
100% правильно. Хотя обычно вы используете анонимные типы для атрибутов Html, на самом деле это IDictionary <string, object>, и поэтому вы можете легко добавлять / удалять из него.
Питер Маннингс,
12
msdn.microsoft.com/en-us/library/… делает то же самое, но встроено в System.Web.Mvc.HtmlHelper.
Мир
1
Почему ToDictionary является общедоступным, а не частным, нет смысла раскрывать этот метод?
Профессор программирования
52

Я предполагаю, что вы имеете в виду здесь анонимные типы, например new { Name1=value1, Name2=value2}и т. Д. Если это так, вам не повезло - анонимные типы являются нормальными типами в том смысле, что они фиксированный, скомпилированный код. Они просто созданы автоматически.

Вы могли бы написать, new { old.Name1, old.Name2, ID=myId }но я не знаю, действительно ли вы этого хотите. Еще несколько подробностей о ситуации (включая примеры кода) были бы идеальными.

В качестве альтернативы вы можете создать объект-контейнер, у которого всегда будет идентификатор, и любой другой объект, содержащий остальные свойства.

Джон Скит
источник
-1
public static string TextBox(this HtmlHelper html, string value, string labelText, string textBoxId, object textBoxHtmlAttributes, object labelHtmlAttributes){}

Это примет значение id, которое должно иметь текстовое поле, и на который должна ссылаться метка. Если потребитель теперь не включает свойство «id» в textBoxHtmlAttributes, метод создаст неправильную метку.

Я могу проверить через отражение, добавлен ли этот атрибут в объект labelHtmlAttributes. Если это так, я хочу добавить его или создать новый анонимный объект, в который он был добавлен. Но поскольку я не могу создать новый анонимный тип, пройдя по старым атрибутам и добавив свой собственный атрибут «id», я как бы застрял.

Контейнер со строго типизированным свойством идентификатора, а затем анонимно типизированным свойством «атрибутов» потребует перезаписи кода, которая не соответствует требованию «добавить поле идентификатора».

Надеюсь, этот ответ понятен. Конец дня, я больше не могу привести в порядок свои мозги ..

Борис Калленс
источник
Что ж ... вы можете создать новый тип (с CodeDOM и т. Д.), Который содержит соответствующие свойства. Но код был бы чертовски уродливым. Могу ли я предложить, чтобы вместо того, чтобы брать объект и смотреть на свойства через отражение, вы использовали IDictionary <string, string> или что-то в этом роде? (Продолжение)
Джон Скит,
Вы можете создать этот словарь с помощью вспомогательного метода, который выполняет все функции отражения - и, возможно, иметь метод-оболочку, который делает именно это, - но словарь звучит так, как будто он ближе к тому, что вы действительно пытаетесь представить; Инициализаторы анонимных объектов просто синтаксически удобны.
Джон Скит,