在.NET中使用select的动态linq表达式

时间:2012-06-18 14:09:03

标签: c# .net linq lambda dynamic-linq

我想动态添加.Select语句,但编译器只允许我在当前范围内构建这些语句。我知道linqkit,这可能是一个解决方案,但我不想添加任何外部功能。我如何避免我现在拥有的代码重复:

 if (request.Equals("some text"))
        {
            var filter = commonFilter.GroupBy(x => new
                {
                    x.Timestamp.Year,
                    x.Timestamp.Month,
                })
                .Select(g => new
                {
                    Year = g.Key.Year,
                    Month = g.Key.Month,
                    TotErr = g.Count(),

                    column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                    column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                    column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                    column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                    column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                    column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                    column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                    column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                    column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                    NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                    NumUsers = g.Select(l => l.UserId).Distinct().Count(),

                });

            return filter.AsPa......;//not important right now
        }
        //Same thing again but slightly different
        else if (request.Equals("some other text"))
        {
            var filter = commonFilter.GroupBy(x => new
                {
                    x.Timestamp.Year,
                    x.Timestamp.Month,
                    x.Timestamp.Day
                })
                .Select(g => new
                {
                    Year = g.Key.Year,
                    Month = g.Key.Month,
                    Day= g.Key.Day,
                    TotErr = g.Count(),

                    column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                    column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                    column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                    column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                    column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                    column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                    column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                    column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                    column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                    NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                    NumUsers = g.Select(l => l.UserId).Distinct().Count(),

                });

            return filter.AsPa......;//not important right now
        }

2 个答案:

答案 0 :(得分:1)

如果要维护匿名类型,可以使用InternalsVisibleToAttribute允许单独的公共库使用匿名类型。

我之前已经这样做过了为带有EF数据源的数据网格创建一个通用的过滤库,但它确实涉及一定程度的反射并使用通用的System.Linq.Expression组件构建表达式,所以这可能不值得,除非你我想要做很多实例。

参见msdn info:

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

如果选择模式更可预测,您可能不需要表达式部分,但在这种情况下,最终只使用公共类而不是匿名类可能更简单。

编辑:“无法将匿名转换为x”类型错误意味着您没有完全/正确地删除匿名。

在每个位置,您都有新的{...无论......},您正在创建一个匿名类型。如果为每个具有正确属性的类创建类以匹配您指定的类,那么您只需更改类似于

的内容
new {x=1,y=2}

阅读

new somenewclass() {x=1,x=2}

假设您已在其他地方定义

public class somenewclass
{
    public int x {get;set;}
    public int y {get;set;}
}

答案 1 :(得分:0)

你可以这样做,

  var Query = commonFilter.Select(g => new
            {
                Year = g.Key.Year,
                Month = g.Key.Month,
                Day= g.Key.Day,
                TotErr = g.Count(),

                column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                NumUsers = g.Select(l => l.UserId).Distinct().Count(),

            });
    if (request.Equals("some text"))
    {
        var filter = Query.GroupBy(x => new
            {
                x.Timestamp.Year,
                x.Timestamp.Month,
            }) ;
    }
    //Same thing again but slightly different
    else if (request.Equals("some other text"))
    {
        var filter = Query.GroupBy(x => new
            {
                x.Timestamp.Year,
                x.Timestamp.Month,
                x.Timestamp.Day
            });
    }