【问题标题】:Using Generics to Create HtmlHelper Extension Methods使用泛型创建 HtmlHelper 扩展方法
【发布时间】:2011-01-25 15:49:10
【问题描述】:

我对创建泛型方法并不是很熟悉,所以我想我应该将这个问题提交给社区并看看会发生什么。它甚至可能不是对泛型的有效使用!

我想创建一个 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" />

有可能吗?还是我看这个完全错误的方式?有人愿意让我了解更好的方法吗?

谢谢

戴夫

【问题讨论】:

  • 这个是可以的,但是除非你传入的类型有有效的html属性,否则会生成无效的html。你确定你要这么做吗?你能详细说明这样做的目的吗?
  • @Baddie,我编辑说“这样做的好处是我可以轻松地将我的 Html 元素序列化为 javascript 对象,以便 jQuerying 到服务器和模型绑定,以及能够指定类型的样式”。我知道它是无效的 Html,但是在 XHTML 文档的上下文中(即它是 XML 的子集,因此可以扩展),可以使用自定义属性吗?

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


【解决方案1】:

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

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】:

    我认为泛型并不是您在这里寻找的。​​p>

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

    1. 让你的所有类都继承自一个通用类,该类具有一个名为“Render”的虚拟方法或类似的东西。这样你就可以调用类的渲染方法。

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

    你会打电话给:

    虽然每个类都必须实现自己的 Render 方法,但您将 1. 避免反射,2. 完全控制基于类的输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 2012-03-11
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 2014-12-21
      相关资源
      最近更新 更多