Fügen Sie dem anonymen Typ nach der Erstellung eine Eigenschaft hinzu


101

Ich verwende ein anonymes Objekt, um meine HTML-Attribute an einige Hilfsmethoden zu übergeben. Wenn der Verbraucher kein ID-Attribut hinzugefügt hat, möchte ich es in meiner Hilfsmethode hinzufügen.

Wie kann ich diesem anonymen Objekt ein Attribut hinzufügen?

Antworten:


17

Wenn Sie versuchen, diese Methode zu erweitern:

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

Obwohl ich sicher bin, dass die Objekterweiterungen von Khaja funktionieren würden, können Sie eine bessere Leistung erzielen, indem Sie ein RouteValueDictionary erstellen und das routeValues-Objekt übergeben, Ihre zusätzlichen Parameter aus dem Kontext hinzufügen und dann mithilfe der ActionLink-Überladung zurückkehren, die ein RouteValueDictionary anstelle eines Objekts verwendet:

Dies sollte den Trick tun:

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

Funktioniert wie ein Zauber, dies sollte die akzeptierte Antwort sein! Übrigens: Wenn Sie bisher die Objektüberladungen von ActionLink () verwenden, müssen Sie htmlAttributes mit HtmlHelper.AnonymousObjectToHtmlAttributes (htmlAttributes) umschließen, um die richtige Überladung aufzurufen!
DR

79

Mit der folgenden Erweiterungsklasse erhalten Sie das, was Sie benötigen.

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% richtig. Obwohl Sie im Allgemeinen anonyme Typen für HTML-Attribute verwenden, handelt es sich tatsächlich um ein IDictionary <Zeichenfolge, Objekt>, und Sie können es daher problemlos hinzufügen / entfernen.
Peter Munnings

12
msdn.microsoft.com/en-us/library/… macht dasselbe, ist jedoch in System.Web.Mvc.HtmlHelper integriert.
Mir

1
Warum ist ToDictionary öffentlich und nicht privat? Es ist nicht sinnvoll, diese Methode verfügbar zu machen.
Professor für Programmierung

52

Ich nehme an, Sie meinen hier anonyme Typen, z new { Name1=value1, Name2=value2}. B. usw. Wenn ja, haben Sie kein Glück - anonyme Typen sind normale Typen, da es sich um festen, kompilierten Code handelt. Sie werden einfach automatisch generiert.

Sie könnten schreiben, new { old.Name1, old.Name2, ID=myId }aber ich weiß nicht, ob Sie das wirklich wollen. Einige weitere Details zur Situation (einschließlich Codebeispiele) wären ideal.

Alternativ können Sie ein Containerobjekt erstellen, das immer eine ID hatte, und jedes andere Objekt, das den Rest der Eigenschaften enthielt.


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

Dies würde den ID-Wert akzeptieren, den das Textfeld haben sollte und auf den sich die Bezeichnung beziehen sollte. Wenn der Verbraucher die Eigenschaft "id" jetzt nicht in die textBoxHtmlAttributes einfügt, erstellt die Methode eine falsche Bezeichnung.

Ich kann durch Reflektion überprüfen, ob dieses Attribut im labelHtmlAttributes-Objekt hinzugefügt wurde. Wenn ja, möchte ich es hinzufügen oder ein neues anonymes Objekt erstellen, dem es hinzugefügt wurde. Aber weil ich keinen neuen anonymen Typ erstellen kann, indem ich durch die alten Attribute gehe und mein eigenes "id" -Attribut hinzufüge, stecke ich irgendwie fest.

Ein Container mit einer stark typisierten ID-Eigenschaft und einer anonym getippten "Attribute" -Eigenschaft würde Code-Umschreibungen erfordern, die nicht der Anforderung "ID-Feld hinzufügen" entsprechen.

Hoffe diese Antwort ist verständlich. Es ist das Ende des Tages, ich kann mein Gehirn nicht mehr in Einklang bringen.


Nun ... Sie könnten einen neuen Typ (mit CodeDOM usw.) erstellen, der die relevanten Eigenschaften enthält. Aber der Code wäre höllisch hässlich. Kann ich vorschlagen, dass Sie, anstatt ein Objekt zu nehmen und die Eigenschaften durch Reflektion zu betrachten, ein IDictionary <string, string> oder so etwas nehmen? (Fortsetzung)
Jon Skeet

Sie könnten dieses Wörterbuch mit einer Hilfsmethode aufbauen, die die gesamte Reflexionssache erledigt hat - und möglicherweise eine Wrapper-Methode, die genau das tut -, aber ein Wörterbuch scheint näher an dem zu sein, was Sie wirklich darstellen möchten. anonyme Objektinitialisierer sind nur syntaktisch praktisch.
Jon Skeet
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.