使用泛型创建HtmlHelper扩展方法

时间:2010-03-09 22:11:33

标签: c# asp.net-mvc extension-methods html-helper

我对创建通用方法并不熟悉,所以我想我会把这个问题提交给社区&看看会有什么回来。它甚至可能不是泛型的有效使用!

我想创建一个HtmlHelper扩展方法,我可以指定该方法属于某种类型。我将该类型的实例和TagBuilder对象的实例传递给该方法。然后我将标记的class属性指定为我传入的对象的类型,并将所有对象的属性序列化为标记的属性。

修改... 这样做的好处是我可以轻松地将我的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" />

甚至可能吗?或者我是以完全错误的方式看待这个?有人愿意让我接受更好的方法吗?

由于

戴夫

2 个答案:

答案 0 :(得分:3)

对于你想要做的事情,我认为使用泛型的主要好处是利用类型推断。如果您按如下方式声明方法:

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

答案 1 :(得分:2)

我认为仿制药并不是你在这里寻找的东西。

相反,您可能想要采用两种不同的方法之一

  1. 让所有类都来自一个普通的类,它有一个名为“Render”的虚拟方法或类似的东西。这样你就可以调用类的render方法。

  2. 让所有类实现一个具有Render方法的接口..

  3. 你要打电话给你:

    虽然每个类都必须实现它自己的Render方法,但你要避免反射,2。在类的基础上完全控制输出。