【问题标题】:LINQ group by query using reflected property nameLINQ group by 使用反射属性名称的查询
【发布时间】:2015-04-17 23:35:41
【问题描述】:

我想用特定对象的公共属性填充下拉列表,我做得很好。但是现在当用户从下拉列表中选择值时,我希望它按该列对数据库表结果进行分组。我曾尝试使用 LINQ,但我只能弄清楚如何按实例变量属性而不是反射属性显式分组。这是我的方法——传入的参数是属性的字符串名称。例如,如果用户想要按 Customer.Country 分组,它将是“Country”,如果用户想要按 Customer.State 分组,它将是“State”。但目前我已经硬编码为按“状态”分组,因为我无法弄清楚如何使用通过我的 LINQ 查询传入的字符串值

private void DisplayReportAction(string category)
{
    if (!string.IsNullOrEmpty(category))
    {
        SelectedCategory = category;
        _summaries.Clear();

        foreach (var custGroup in _customerInterface.CustomerInterface.GetAllCustomers().GroupBy(c => c.State)
            .Select(group => new
                                 {
                                     Category = group.Key,
                                     Count = group.Count()
                                 })
                                 .OrderBy(x => x.Category))
        {
            _summaries.Add(new CustomerReportSummaryViewModel(custGroup.Category, custGroup.Count));
        }

        ReportVisibility = Visibility.Visible;
    }
}

【问题讨论】:

    标签: c# linq reflection


    【解决方案1】:

    如果你使用 LINQ to Objects,你可以使用反射,例如你可以使用这个:

    _customerInterface.CustomerInterface.GetAllCustomers()
         .GroupBy(c => c.GetType().GetProperty(category).GetValue(c, null))
    

    如果您使用的是 Linq To Sql,那么另一种方法是使用动态查询,请查看此链接

    http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

    【讨论】:

    • 通过一次修改效果很好。上面的代码将返回属性对象,如果你按属性名称分组,你会得到一个带有属性名称标签的单个存储桶下返回的所有内容。要使其正常工作,您需要使 group by 子句 ".GroupBy(c => c.GetType().GetProperty(category).GetValue(c, null))"
    • @user1122909,我明白了,你是对的,更新答案,谢谢!
    【解决方案2】:

    您可以动态构建表达式:

        Expression<Func<Customer,T>> buildExpression<T>(string category)
        {
            //First build parameter of lambda ( 'c =>' part of expression)
            ParameterExpression param = Expression.Parameter(typeof(Customer), "c");
            //Then body of expression : ' => c.category'
            Expression<Func<Customer, T>> exp = Expression.Lambda<Func<Customer, T>>(Expression.Property(param, category), param);
            return exp;
        }
    

    最后,调用

    _customerInterface.CustomerInterface.GetAllCustomers()
        .GroupBy(buildExpression(category))
    

    编辑: 好吧,对不起,您仍然需要知道属性的类型才能将 T 类型参数赋予buildExpression 函数

    有一些方法可以做到这一点,例如使用GetProperty(category).PropertyType,然后在GetType().GetMethod("buildExpression&lt;&gt;") 上调用MakeGenericMethod,但这需要更多的工作。 无论如何,你必须想办法从这种类型构建CustomerReportSummaryViewModel

    我不知道您的用例,但您可能所有类别属性都属于同一类型,因此您可以对其进行硬编码?

    如果您有兴趣,但找不到合适的方法,请告诉我,我会尝试编写合适的解决方案。

    【讨论】:

      猜你喜欢
      • 2014-02-12
      • 1970-01-01
      • 2015-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多