Tambahkan properti ke tipe anonim setelah pembuatan

101

Saya menggunakan objek anonim untuk meneruskan Atribut Html saya ke beberapa metode pembantu. Jika konsumen tidak menambahkan atribut ID, saya ingin menambahkannya di metode helper saya.

Bagaimana cara menambahkan atribut ke objek anonim ini?

Boris Callens
sumber

Jawaban:

17

Jika Anda mencoba memperluas metode ini:

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

Meskipun saya yakin ekstensi Object Khaja akan berfungsi, Anda mungkin mendapatkan kinerja yang lebih baik dengan membuat RouteValueDictionary dan meneruskan objek routeValues, tambahkan parameter tambahan Anda dari Context, lalu kembali menggunakan overload ActionLink yang mengambil RouteValueDictionary alih-alih objek:

Ini harus melakukan trik:

    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);
    }
Levitikon
sumber
Bekerja seperti pesona, ini harus menjadi jawaban yang diterima! BTW: Jika sejauh ini Anda menggunakan objek overloads ActionLink (), Anda harus membungkus htmlAttributes dengan HtmlHelper.AnonymousObjectToHtmlAttributes (htmlAttributes) untuk memanggil overload yang benar!
DR
79

Kelas ekstensi berikut akan memberi Anda apa yang Anda butuhkan.

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;
    }
}
Khaja Minhajuddin
sumber
4
100% benar. Meskipun secara umum Anda menggunakan tipe anonim untuk Atribut Html, ini sebenarnya adalah IDictionary <string, object> dan oleh karena itu Anda dapat menambahkan / menghapusnya dengan mudah.
Peter Munnings
12
msdn.microsoft.com/en-us/library/… melakukan hal yang sama, tetapi itu dibangun ke dalam System.Web.Mvc.HtmlHelper.
Mir
1
Mengapa ToDictionary bersifat publik dan bukan pribadi, tidak masuk akal untuk mengekspos metode ini?
Profesor pemrograman
52

Saya berasumsi yang Anda maksud adalah tipe anonim di sini, misalnya, new { Name1=value1, Name2=value2}dll. Jika demikian, Anda kurang beruntung - tipe anonim adalah tipe normal karena mereka tetap, kode terkompilasi. Mereka kebetulan dibuat secara otomatis.

Apa yang dapat Anda lakukan adalah menulis new { old.Name1, old.Name2, ID=myId }tetapi saya tidak tahu apakah itu yang Anda inginkan. Beberapa detail lebih lanjut tentang situasi (termasuk contoh kode) akan ideal.

Alternatifnya, Anda bisa membuat objek kontainer yang selalu memiliki ID dan objek lain apa pun yang berisi properti lainnya.

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

Ini akan menerima nilai id yang seharusnya dimiliki kotak teks dan label yang harus dirujuk. Jika konsumen sekarang tidak menyertakan properti "id" di textBoxHtmlAttributes, metode ini akan membuat label yang salah.

Saya dapat memeriksa melalui refleksi jika atribut ini ditambahkan di objek labelHtmlAttributes. Jika demikian, saya ingin menambahkannya atau membuat objek anonim baru yang telah ditambahkannya. Tetapi karena saya tidak dapat membuat tipe anonim baru dengan menelusuri atribut lama dan menambahkan atribut "id" saya sendiri, saya agak macet.

Sebuah penampung dengan properti ID yang diketik dengan kuat dan kemudian properti "atribut" yang diketik secara anonim akan memerlukan penulisan ulang kode yang tidak membebani persyaratan "tambahkan bidang id".

Semoga tanggapan ini bisa dimengerti. Ini akhir hari, tidak bisa otak saya sejalan lagi ..

Boris Callens
sumber
Nah ... Anda bisa membuat tipe baru (dengan CodeDOM dll) yang berisi properti yang relevan. Tapi kodenya akan jelek sekali. Dapatkah saya menyarankan bahwa alih-alih mengambil objek dan melihat properti melalui refleksi, Anda mengambil IDictionary <string, string> atau sesuatu? (Lanjutan)
Jon Skeet
Anda bisa membangun kamus itu dengan metode helper yang melakukan keseluruhan refleksi - dan mungkin memiliki metode pembungkus yang melakukan hal itu dengan tepat - tetapi kamus kedengarannya lebih dekat dengan apa yang sebenarnya Anda coba wakili; penginisialisasi objek anonim hanya berguna secara sintaksis.
Jon Skeet