【问题标题】:Modify lambda expression in extension method在扩展方法中修改 lambda 表达式
【发布时间】:2014-02-06 10:24:27
【问题描述】:

我正在尝试使用泛型创建一个扩展方法,您会在其中收到一个列表 任何类,例如:

 class User
 {
  public string name {get;set;}
  public int age {get;set;}
  public string lastLogon {get;set;}
 }

我正在尝试构建一个表达式,您可以在其中将 IEnumerable 传递给扩展方法,并指定哪个是字符串日期属性。 (在这种情况下lastLogon)

没有扩展方法应该是这样的:

userList.OrderBy(x => Convert.ToDateTime(x.lastLogon));

这是我到目前为止所做的:

 public static IEnumerable<TSource> OrderEnumerablebyDatetimeString<TSource,TKey>(
            this IEnumerable<TSource> input, Func<TSource, TKey> funcexpr)
        {
            //modify expression to get the date field and modify the lambda expr
            Expression<Func<TSource, TKey>> expr = ???

            return input.OrderBy(funcexpr);

        }

我的最终分机电话应如下所示:

userList.OrderEnumerablebyDatetimeString(x => x.lastLogon);

【问题讨论】:

  • 使用Expression&lt;Func&lt;TSource, TKey&gt;&gt; funcexpr 而不是Func&lt;TSource, TKey&gt; funcexpr
  • Grundy 是对的,如果这是 Linq-to-SQL。
  • @JeppeStigNielsen 我的意思是修改后调用Compile 并使用IEnumerable
  • 这是对象的 linq

标签: c# .net lambda linq-to-objects func


【解决方案1】:

这是我为你准备的:

public static IEnumerable<TSource> OrderEnumerablebyDatetimeString<TSource>(
this IEnumerable<TSource> input, Func<TSource, string> funcexpr)
{
    Func<TSource, DateTime> expr = (x=>Convert.ToDateTime(funcexpr(x)));

    return input.OrderBy(expr);

}

请注意,我删除并更改了一些通用参数以更准确地反映您所拥有的。你说过你总是传入一个字符串,所以你传入的乐趣应该总是返回一个字符串。同样,您为 orderby 创建的表达式将始终返回 DateTime,因此我已对其进行硬编码。

关键点当然是调用传递的Func从对象中获取日期字符串。

为了更详细地解释(根据 cmets 中的要求)funcexpr(x) 正在调用您传入的函数,并将 x 作为其参数。它很像调用任何其他方法,除了您的方法在变量中。具体来说,func 已被声明为接受对象并返回string 的方法。在这种情况下,字符串是来自对象的日期字符串,在我们的示例中是用户。所以funcexpr(x) 将返回日期字符串,然后按照您的预期通过 convert 转换为 DateTime。

我还应该注意完整性,这是在 Linq to Objects 上下文中完成和测试的。既然您在谈论与List&lt;User&gt; 合作,我假设就是这种情况。

这里还有一个工作示例的链接,包括字符串排序以证明其正常工作:http://dotnetfiddle.net/r3Lq0P

【讨论】:

  • IEnumerable 扩展需要Func 而不是Expression
  • @Grundy:鉴于上面的代码已经过测试并且可以在 linqpad 中运行,因此需要可能过于强大。你是对的,它不需要它,所以删除它会更干净。
  • 刚刚注意到我的测试令人震惊,尽管我没有使用 expr。 ;-)
  • 我尝试了您的建议,但它没有订购列表。这里有一个例子:pastebin.com/05eHKr51
  • 在您的示例中,它们已经按日期顺序排列,因此不应有任何更改。 pastebin.com/7m97Qk5C 是我在 LinqPad 中用于测试的代码,它在运行时将顺序更改为 test3、test1、test2。在这个测试中,我在字符串中使用的日期格式旨在确保字符串和日期的比较会产生不同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
相关资源
最近更新 更多