作成後にプロパティを匿名型に追加する


101

匿名オブジェクトを使用して、HTML属性をいくつかのヘルパーメソッドに渡します。コンシューマーがID属性を追加しなかった場合は、ヘルパーメソッドに追加します。

この匿名オブジェクトに属性を追加するにはどうすればよいですか?

回答:


17

このメソッドを拡張しようとしている場合:

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

Khajaのオブジェクト拡張が機能すると確信していますが、RouteValueDictionaryを作成してrouteValuesオブジェクトを渡し、Contextから追加のパラメーターを追加して、オブジェクトの代わりにRouteValueDictionaryを受け取るActionLinkオーバーロードを使用して返すことで、パフォーマンスが向上する場合があります。

これでうまくいくはずです:

    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>であるため、そこから簡単に追加/削除できます。
Peter Munnings 2012年

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 }、それが本当にあなたが望んでいることかどうかはわかりません。状況の詳細(コードサンプルを含む)が理想的です。

または、常に IDを持ち、その他のプロパティを含むその他のオブジェクトを持つコンテナオブジェクトを作成することもできます。


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

これは、テキストボックスとラベルが参照するID値を受け入れます。コンシューマーがtextBoxHtmlAttributesに「id」プロパティを含めない場合、メソッドは誤ったラベルを作成します。

この属性がlabelHtmlAttributesオブジェクトに追加されているかどうかをリフレクションで確認できます。もしそうなら、それを追加するか、それを追加した新しい匿名オブジェクトを作成します。しかし、古い属性を調べて独自の「id」属性を追加することで新しい匿名型を作成することができないので、ちょっと行き詰まっています。

厳密に型指定されたIDプロパティと、その後に匿名で型指定された「属性」プロパティを持つコンテナでは、「IDフィールドの追加」の要件を満たさないコードの書き換えが必要になります。

この反応が理解できることを願っています。一日の終わりです。もう頭がおかしくなりません。


まあ...あなたは関連するプロパティを含む新しいタイプ(CodeDOMなどで)を作成できます。しかし、コードは地獄のように醜いでしょう。オブジェクトを取得してリフレクションでプロパティを確認する代わりに、IDictionary <string、string>などを使用することを提案できますか?(続き)
ジョンスキート、

リフレクション全体を実行するヘルパーメソッドを使用してそのディクショナリを構築できます-おそらくそれを正確に実行するラッパーメソッドを使用できますが、ディクショナリは実際に表現しようとしているものに近いように聞こえます。匿名オブジェクト初期化子は、構文的に便利です。
Jon Skeet、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.