Dodaj właściwość do typu anonimowego po utworzeniu


101

Używam anonimowego obiektu, aby przekazać moje atrybuty HTML do niektórych metod pomocniczych. Jeśli konsument nie dodał atrybutu identyfikatora, chcę dodać go w mojej metodzie pomocniczej.

Jak mogę dodać atrybut do tego anonimowego obiektu?

Odpowiedzi:


17

Jeśli próbujesz rozszerzyć tę metodę:

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

Chociaż jestem pewien, że rozszerzenia Object Khaji będą działać, możesz uzyskać lepszą wydajność, tworząc RouteValueDictionary i przekazując obiekt routeValues, dodaj swoje dodatkowe parametry z Context, a następnie wróć przy użyciu przeciążenia ActionLink, które pobiera RouteValueDictionary zamiast obiektu:

To powinno załatwić sprawę:

    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);
    }

Działa jak urok, to powinna być akceptowana odpowiedź! BTW: Jeśli do tej pory używasz przeciążeń obiektów ActionLink (), musisz zawijać htmlAttributes z HtmlHelper.AnonymousObjectToHtmlAttributes (htmlAttributes), aby wywołać prawidłowe przeciążenie!
DR

79

Następująca klasa rozszerzeń zapewni Ci to, czego potrzebujesz.

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% poprawne. Chociaż generalnie używasz anonimowych typów dla atrybutów html, w rzeczywistości jest to IDictionary <string, object> i dlatego możesz łatwo dodać / usunąć z niego.
Peter Munnings,

12
msdn.microsoft.com/en-us/library/… robi to samo, ale jest wbudowany w System.Web.Mvc.HtmlHelper.
Mir

1
Dlaczego ToDictionary jest publiczny, a nie prywatny, nie ma sensu ujawniać tej metody?
Profesor programowania

52

Zakładam, że masz tu na myśli typy anonimowe, np. new { Name1=value1, Name2=value2}Itd. Jeśli tak, to nie masz szczęścia - typy anonimowe są typami normalnymi, ponieważ są to ustalony, skompilowany kod. Tak się składa, że ​​są generowane automatycznie.

Co mógł zrobić, to napisać new { old.Name1, old.Name2, ID=myId }, ale nie wiem, czy to naprawdę to, co chcesz. Bardziej szczegółowe informacje na temat sytuacji (w tym próbki kodu) byłyby idealne.

Alternatywnie możesz utworzyć obiekt kontenera, który zawsze miał identyfikator i jakikolwiek inny obiekt zawierał pozostałe właściwości.


-1
public static string TextBox(this HtmlHelper html, string value, string labelText, string textBoxId, object textBoxHtmlAttributes, object labelHtmlAttributes){}

To zaakceptowałoby wartość id, którą powinno mieć pole tekstowe i do której powinna odnosić się etykieta. Jeśli konsument nie uwzględni teraz właściwości „id” w atrybucie textBoxHtmlAttributes, metoda utworzy niepoprawną etykietę.

Mogę sprawdzić poprzez refleksję, czy ten atrybut został dodany do obiektu labelHtmlAttributes. Jeśli tak, chcę go dodać lub utworzyć nowy anonimowy obiekt, do którego został dodany. Ale ponieważ nie mogę utworzyć nowego typu anonimowego, przechodząc przez stare atrybuty i dodając własny atrybut „id”, utknąłem.

Kontener z silnie wpisaną właściwością ID, a następnie anonimową właściwością „atrybutów” wymagałby przepisania kodu, który nie ważyłby więcej niż wymaganie „dodaj pole identyfikatora”.

Mam nadzieję, że ta odpowiedź jest zrozumiała. To koniec dnia, nie mogę już uporządkować swoich mózgów.


Cóż ... mogłaby utworzyć nowy typ (z CodeDOM etc), który zawierał odpowiednie właściwości. Ale kod byłby brzydki jak diabli. Czy mogę zasugerować, że zamiast brać obiekt i patrzeć na właściwości przez odbicie, bierzesz IDictionary <string, string> lub coś takiego? (Ciąg dalszy)
Jon Skeet

Mógłbyś zbudować ten słownik za pomocą metody pomocniczej, która wykonałaby całą refleksję - i prawdopodobnie mieć metodę opakowującą, która właśnie to zrobiła - ale słownik brzmi tak, jakby był bliżej tego, co naprawdę próbujesz przedstawić; anonimowe inicjatory obiektów są po prostu przydatne pod względem składniowym.
Jon Skeet
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.