Использование обобщений для создания методов расширения HtmlHelper - PullRequest
1 голос
/ 10 марта 2010

Я не очень знаком с созданием универсальных методов, поэтому я решил задать этот вопрос сообществу и посмотреть, что получится. Это может быть даже недопустимое использование дженериков!

Я хотел бы создать метод расширения HtmlHelper, в котором я могу указать, что этот метод имеет определенный тип. Я передаю в метод экземпляр этого типа и экземпляр объекта TagBuilder. Затем я указываю атрибут класса тега как тип объекта, который я передал, и все свойства объекта сериализуются в атрибуты тега.

редактировать ... Преимущество этого состоит в том, что я мог бы легко сериализовать мои элементы Html в объекты javascript для jQuerying для сервера и привязки модели, а также возможность указать стиль для типа. ... конец редактирования

Этот пример кода может прояснить.

У меня есть такой тип:

public class MyType
{
    public int Prop1 { get; set; }
    public int Prop2 { get; set; }

    public MyType(int val1, int val2)
    {
        this.Prop1 = val1;
        this.Prop2 = val2;
    }
}

Я думаю о том, чтобы создать вспомогательный метод, возможно, с подписью, подобной этой:

public static string GetTag<T>(this HtmlHelper h, object myType, TagBuilder tag)
{
    // cast myType to T //(i.e. MyType)
    // use reflection to get the properties in MyType
    // get values corresponding to the properties
    // build up tag's attribute/value pairs with properties.
}

В идеале я мог бы тогда позвонить:

<% var myType = new MyType(123, 234); %>
<% var tag = new TagBuilder("div"); %>
<%= Html.GetTag<MyType>(myType, tag) %>

и полученный html будет

<div class="MyType" prop1="123" prop2="234" />

А позже я могу позвонить

<%= Html.GetTag<MyOtherType>(myOtherType, tag) %>

чтобы получить

<div class="MyOtherType" prop1="123" prop2="234" />

Возможно ли это вообще? Или я смотрю на это совершенно неправильно? Кто-нибудь хочет, чтобы меня лучше подходило?

Спасибо

Dave

Ответы [ 2 ]

3 голосов
/ 10 марта 2010

Для того, что вы пытаетесь сделать, я думаю, что основным преимуществом использования обобщений будет использование вывода типов. Если вы объявите свой метод следующим образом:

public static string GetTag<T>(this HtmlHelper h, T myObj, TagBuilder tag)

Вам не нужно указывать параметр типа при его вызове, потому что он будет выведен из использования (т. Е. Компилятор увидит, что тип второго параметра равен MyType, поэтому он будет догадываться, что T == MyType ).

Но в любом случае вам не нужно указывать тип: метод может вызвать GetType для объекта и использовать результирующий тип так же, как он использовал бы typeof(T), так что дженерики не такие полезно здесь.

Однако я вижу одну причину использовать их в любом случае: если у вас есть объект типа MySubType, который наследуется от MyType, вы можете захотеть отображать только свойства, определенные в MyType: в этом случае вы просто необходимо указать MyType в качестве параметра типа, переопределяя вывод типа.

Вот возможная реализация:

public static string GetTag<T>(this HtmlHelper h, T myObj, TagBuilder tag)
{
    Type t = typeof(T);
    tag.Attributes.Add("class", t.Name);
    foreach (PropertyInfo prop in t.GetProperties())
    {
        object propValue = prop.GetValue(myObj, null);
        string stringValue = propValue != null ? propValue.ToString() : String.Empty;
        tag.Attributes.Add(prop.Name, stringValue);
    }
    return tag.ToString();
}
2 голосов
/ 10 марта 2010

Я думаю, что дженерики не совсем то, что вы ищете здесь.

Вместо этого вы можете выбрать один из двух разных подходов

  1. Сделайте так, чтобы все ваши классы происходили из общего класса, в котором есть виртуальный метод Render или что-то похожее. Таким образом, вы можете просто вызвать метод визуализации классов.

  2. Сделайте так, чтобы все ваши классы реализовали Интерфейс с методом Render.

То, что вы назвали бы:

Хотя каждый класс затем должен реализовать свой собственный метод Render, вы должны: 1. избежать рефлексии, 2. иметь полный контроль над классом в зависимости от того, что выводится.

...