简体   繁体   English

使用泛型创建HtmlHelper扩展方法

[英]Using Generics to Create HtmlHelper Extension Methods

I'm not really familiar with creating generic methods, so I thought I'd put this question to the community & see what comes back. 我对创建泛型方法并不十分熟悉,因此我想将这个问题提交给社区并看看会回来什么。 It might not even be a valid use of generics! 甚至可能不是有效使用泛型!

I'd like to create a HtmlHelper extension method where I can specify that the method is of a certain type. 我想创建一个HtmlHelper扩展方法,在其中可以指定该方法为某种类型。 I pass into the method an instance of that type, and an instance of a TagBuilder object. 我将这种类型的实例和TagBuilder对象的实例传递给方法。 I then specify the class attribute of the tag to be the type of object I passed in, with all the object's properties serialized into the tag's attributes. 然后,我将标签的class属性指定为我传入的对象的类型,并将所有对象的属性序列化为标签的属性。

edit... the benefit of this would be that I could then easily serialize my Html elements in into javascript objects for jQuerying to the server & Model Binding, as well as the ability to specify style for a type ...end edit 编辑...这样做的好处是,我可以轻松地将Html元素序列化为javascript对象,以便将jQuerying到服务器和模型绑定,以及为类型指定样式的能力...结束编辑

This code sample might clarify. 此代码示例可能会阐明。

I have a type like this: 我有这样的类型:

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

What I'm thinking is to produce a helper method, maybe with a signature similar to this: 我在想的是产生一个辅助方法,也许带有类似于以下的签名:

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.
}

Ideally I could then call: 理想情况下,我可以打电话给:

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

and the html produced would be 和产生的HTML将是

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

And later on, I can call 然后,我可以打电话

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

to get 要得到

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

Is it even possible? 可能吗? Or am I looking at this totally the wrong way? 还是我看这是完全错误的方式? Anyone care to fill me on on a better approach? 有人愿意让我采用更好的方法吗?

Thanks 谢谢

Dave 戴夫

For what you're trying to do, I think the main benefit of using generics would be to take advantage of type inference. 对于您要尝试执行的操作,我认为使用泛型的主要好处是可以利用类型推断。 If you declare your method as follows : 如果您声明方法如下:

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

You won't have to specify the type parameter when calling it, because it will be inferred from the usage (ie the compiler will see that the second parameter's type is MyType , so it will guess that T == MyType). 您不必在调用时指定类型参数,因为它将根据用法进行推断(即,编译器将看到第二个参数的类型为MyType ,因此它将猜测T == MyType)。

But anyway, you don't really need to specify the type : the method could call GetType on the object, and use the resulting type the same way it would have used typeof(T) , so generics aren't so useful here. 但是无论如何,您实际上并不需要指定类型:该方法可以在对象上调用GetType ,并以与使用typeof(T)相同的方式使用结果类型,因此泛型在这里并不是那么有用。

However, I see one reason to use them anyway : if you have an object of type MySubType , which inherits from MyType , you might want to render only properties defined in MyType : in that case you just have to specify MyType as the type parameter, overriding the type inference. 但是,无论如何,我仍然看到使用它们的一个原因:如果您有一个MySubType类型的对象,该对象继承自MyType ,则可能只希望呈现MyType中定义的属性:在这种情况下,您只需指定MyType作为类型参数,覆盖类型推断。

Here's a possible implementation : 这是一个可能的实现:

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

I'm thinking generics is not exactly what you are looking for here. 我在想泛型不完全是您在这里寻找的东西。

Instead you might want to take one of two different approaches 相反,您可能想采用两种不同的方法之一

  1. Make all of your classes descend from a common one which has a virtual method called "Render" or something similiar. 使所有类都继承自一个通用类,该通用类具有一个称为“ Render”或类似名称的虚拟方法。 That way you can just call the classes render method. 这样,您可以只调用类render方法。

  2. Make all of your classes implement an Interface which has a Render method.. 使所有类都实现具有Render方法的Interface。

That you you would just call: 您会打电话给您:

Although each class then has to implement it's own Render method, you would 1. avoid reflection, 2. have complete control on a class basis on what the output is. 尽管每个类都必须实现自己的Render方法,但您还是应该1.避免反射,2.在类的基础上完全控制输出内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM