将匿名对象合并为单个匿名对象

时间:2014-06-29 22:02:12

标签: c# asp.net-mvc

在某些情况下,我需要传递一些路由值组合来创建特定路由的URL。而不是使用混淆堆叠的if-cases,例如:

(x != 0 && y != 0 ? (object)new { xId = 1, yId = 1 } : (x != 0 ? (object)new { xId = 1 } : (y != 0 ? (object)new { yId = 1 } : null)))

这是2个值的4种可能组合(两种,一种或另一种,无)。

(如果你想知道为什么我需要if-cases,这是一个有很多页面/链接的模板,但是根据它的使用方式,路由可以稍微不同地设置,而不是必须找到并更改每个链接我希望能够根据路由的设置方式不同地应用路由值,如果我不这样做,它会为没有映射到路由值的值添加无用的查询字符串)

为了使这更容易阅读,有一个合并匿名类型的方法会很棒,例如:

Merge((x != 0 ? new { xId = 1 } : null), (y != 0 ? new { yId = 1 } : null))

我找到了这个解决方案https://stackoverflow.com/a/6802728但我有一个问题,我认为这归结为我对这里所处理的内容的理解。

以下是此方法的变体:

public static dynamic Merge(params object[] objects)
{
    dynamic expando = new ExpandoObject();
    var merged = expando as IDictionary<string, object>;

    foreach (object obj in objects)
        if (obj != null)
            foreach (PropertyInfo property in obj.GetType().GetProperties())
                merged[property.Name] = property.GetValue(obj);

    return merged;
}

当我将此方法的输出(路由值)以及路由名称传递给HtmlHelper时,期望它创建具有指定URL的html链接,但由于找不到匹配的路由,因此无法执行此操作。它似乎无法访问合并对象中的路由值。方法返回类型是动态的,并且转换为对象或RouteValueDictionary没有区别。

输出对象与普通匿名对象有什么不同?有没有办法让它能够访问合并对象中的键/值?

2 个答案:

答案 0 :(得分:3)

在ASP.NET MVC中,Url.ActionHtml.ActionLink等HTML帮助程序也有重载,需要RouteValueDictionary。例如:

@{ var x = 1; var y = 1; }

@Html.ActionLink(
    "Go to contacts", "Contact", "Home",
    routeValues: 
        Merge(x != 0 ? new { xId = 1 } : null, y != 0 ? new { yId = 1 } : null),
    htmlAttributes: null))

使用此重载,您可以通过以下方式实现Merge方法:

public static RouteValueDictionary Merge(params object[] routeValuesObjects)
{
    var result = new RouteValueDictionary();

    foreach (var routeValues in routeValuesObjects)
        foreach (var item in new RouteValueDictionary(routeValues))
            result[item.Key] = item.Value;

    return result;
}

答案 1 :(得分:1)

匿名对象(实际上,编译时语法糖以一个由编译器指定的随机名称的常规类结尾)与ExpandoObjectDynamicObject的实现不同。

动态对象并不真正公开属性,但这些属性在运行时被解析。

我猜ASP.NET MVC使用常规反射无法访问ExpandoObject中的反射和属性来检查这些匿名对象。也就是说,路由应该使用动态对象实现特定代码来处理路由参数,以处理您的用例。

建议...

可悲的是,我相信你需要保持目前的态度。有时候我们想要一个神奇的解决方案,但如果这在你的场景中运行良好,我会避免过于复杂的代码。