创建后将属性添加到匿名类型


101

我使用匿名对象将Html属性传递给一些辅助方法。如果使用者没有添加ID属性,那么我想在我的助手方法中添加它。

如何向该匿名对象添加属性?

Answers:


17

如果您尝试扩展此方法:

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

尽管我确定Khaja的Object扩展会起作用,但是您可以通过创建RouteValueDictionary并传入routeValues对象,从Context中添加其他参数,然后使用ActionLink重载(使用RouteValueDictionary而不是对象)来返回来获得更好的性能:

这应该可以解决问题:

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

像魅力一样工作,这应该是公认的答案!顺便说一句:到目前为止,如果您正在使用ActionLink()的对象重载,则必须使用HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)包装htmlAttributes才能调用正确的重载!
DR

79

以下扩展类将为您提供所需的内容。

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

4
100%正确。即使通常将Html属性使用匿名类型,它实际上也是IDictionary <string,object>,因此您可以轻松地从中添加/删除。
Peter Munnings 2012年

12
msdn.microsoft.com/zh-cn/library/…做了同样的事情,但是它内置在System.Web.Mvc.HtmlHelper中。
Mir

1
为什么ToDictionary是公开的而不是私有的,公开这种方法没有意义?
程序设计教授

52

我假设您是在这里指匿名类型,例如,new { Name1=value1, Name2=value2}等等。如果是这样,那您就不走运了-匿名类型是常规类型,因为它们是固定的已编译代码。它们恰好是自动生成的。

可以做的就是写,new { old.Name1, old.Name2, ID=myId }但是我不知道那是否真的是您想要的。有关这种情况的更多详细信息(包括代码示例)将是理想的。

另外,您可以创建一个容器对象 始终具有一个ID,而其他任何对象都包含其余的属性。


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

这将接受文本框应具有的id值,并且标签应引用该ID值。如果使用者现在在textBoxHtmlAttributes中不包含“ id”属性,则该方法将创建错误的标签。

我可以通过反射检查是否将此属性添加到labelHtmlAttributes对象中。如果是这样,我想添加它或创建一个添加了它的新匿名对象。但是因为无法通过遍历旧属性并添加自己的“ id”属性来创建新的匿名类型,所以我有些困惑。

具有强类型ID属性,然后具有匿名类型“属性”属性的容器将要求代码重写不符合“添加ID字段”的要求。

希望这种反应是可以理解的。今天到头了,我的脑子再也无法排成一列。


好吧...您可以创建一个包含相关属性的新类型(使用CodeDOM等)。但是代码会很丑陋。我是否建议您采取IDictionary <string,string>之类的方法,而不是通过反射来查看对象和属性?(续)
乔恩·斯基特

您可以使用辅助方法来构建该词典,该方法可以完成整个反射工作-可能还可以使用包装方法来精确地完成该任务-但是词典听起来像它更接近于您真正想表达的内容;匿名对象初始化器在语法上很方便。
乔恩·斯基特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.