如何将LINQ结果传递给方法?

时间:2015-11-19 13:50:26

标签: c# linq data-structures anonymous-types

Efficient data structure to hold employee's activities?,我有一个ActividadEmpleado类型的列表,声明为:

public string Empleado { get; set; }
public DateTime Fecha { get; set; }
public string Actividad { get; set; }

LINQ查询变量以我需要的方式重新排序结果,即按日期存储,然后按ActividadEmpleado和字符串存储。但是,var类型不能传递给方法,所以搜索这个站点我发现我需要创建一个类来存储结果或修改LINQ变量来返回List,但是我遇到了正确的声明问题

LINQ变量是:

var queryActividades = listaActividad
                .GroupBy(a => a.Fecha, (fecha, fechaActividades) => new
                {
                    Fecha = fecha,
                    FechaActividades = fechaActividades
                        .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => new
                        {
                            Actividades = actividadesEmpleado,
                            NombreEmpleado = nombreEmpleado
                        })
                        .OrderBy(a => a.NombreEmpleado)
                })
                .OrderBy(a => a.Fecha);

Visual Studio说queryActividades是:

IOrderedEnumerable<'a>
Anonymous Types:
'a new datetime fecha, iorderedenumerable<'b>
'b new IEnumerable<ActividadEmpleado> Actividades, string NombreEmpleado

我需要将queryActividades传递给另一个方法。我尝试将其作为对象传递,但后来我失去了扩展方法,例如Where&lt;&gt; (我可以以某种方式投出它吗?)

我还读到,将结果声明为元组应该有效,但我认为声明一个新类更清晰。

我刚刚开始使用LINQ,我已经避免使用常规数据结构,但在这种情况下它非常有用,并且想知道如何处理它们中的匿名类型或将结果转换为常规List

最终解决方案:

class GrupoActividad
{
    public DateTime Fecha { get; set; }
    public IEnumerable<Actividad> Actividades { get; set; }
}

class Actividad
{
    public IEnumerable<ActividadEmpleado> Actividades { get; set; }
    public string NombreEmpleado { get; set; }
}

var queryActividades = listaActividad
                .GroupBy(a => a.Fecha, (fecha, fechaActividades) => new GrupoActividad
                {
                    Fecha = fecha,
                    Actividades = fechaActividades
                        .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => new Actividad
                        {
                            Actividades = actividadesEmpleado,
                            NombreEmpleado = nombreEmpleado
                        })
                        .OrderBy(a => a.NombreEmpleado)
                })
                .OrderBy(a => a.Fecha);

接收方式:

var actividades = from a in queryActividades
                       where a.Fecha == fechaCiclo
                       select new { a.Fecha, a.Actividades };
            foreach (var item in actividades)
            {
                //cycle that holds each day's activities
                foreach (var empleado in item.Actividades)
                {
                    //cycle that holds each employee with activities in that day
                    foreach (var actividad in empleado.Actividades)
                    {
                        //final cycle that actually reads the activity
                        ActividadEmpleado actividadEmpleado = (ActividadEmpleado)actividad;
                    }
                }
            }

3 个答案:

答案 0 :(得分:4)

现在你正在创建一个基于匿名类型(实际上是两个匿名类型)的集合,它实际上不能传递给另一个方法(除了使用反射或dynamic)。最干净的方法是创建一个表示集合的具体类型 - 类似于

public class ActivityGroup
{
    public DateTime Fecha {get; set;}
    public IEnumerable<Activity> Activities {get; set;}
}

public class Activity
{
    public IEnumerable<Activity> Actividades {get; set;}
    public string NombreEmpleado {get; set;}
}

然后将您的查询更改为:

var queryActividades = listaActividad
                .GroupBy(a => a.Fecha, (fecha, fechaActividades) => new ActivityGroup
                {
                    Fecha = fecha,
                    FechaActividades = fechaActividades
                        .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => new Activity
                        {
                            Actividades = actividadesEmpleado,
                            NombreEmpleado = nombreEmpleado
                        })
                        .OrderBy(a => a.NombreEmpleado)
                })
                .OrderBy(a => a.Fecha);

并将其作为IEnumerable<ActivityGroup>

传递

答案 1 :(得分:2)

您可以使用D Stanley提供的方法。但是,为将来编写的任何类似查询创建这样的类会很无聊。相反,您可以为此引入泛型类,如此

public class Grouping<TKey, TElement>
{
    public TKey Key { get; set; }
    public IEnumerable<TElement> Elements { get; set; }
}

并使用它而不是像这样的匿名类型

var queryActividades = listaActividad
    .GroupBy(a => a.Fecha, (fecha, fechaActividades) => new Grouping<DateTime, Grouping<string, ActividadEmpleado>>
    {
        Key = fecha,
        Elements = fechaActividades
            .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => new Grouping<string, ActividadEmpleado>
            {
                Key = nombreEmpleado,
                Elements = actividadesEmpleado
            })
            .OrderBy(a => a.Key)
    })
    .OrderBy(a => a.Key);

可以作为IEnumerable<Grouping<DateTime, Grouping<string, ActividadEmpleado>>>传递。

正如您所看到的,可重用性和可读性之间存在折衷。基本上这是一个Tuple,有一些更有意义的名字。请注意,尽管我们无法改善结果中的详细程度,但我们可以使用类似于Tuple.Create的技术来删除查询中的详细程度,方法是添加类似这样的类

public static class Grouping
{
    public static Grouping<TKey, TElement> Create<TKey, TElement>(TKey key, IEnumerable<TElement> elements)
    {
        return new Grouping<TKey, TElement> { Key = key, Elements = elements };
    }
}

并像这样使用

var queryActividades = listaActividad
    .GroupBy(a => a.Fecha, (fecha, fechaActividades) => Grouping.Create(
        fecha, fechaActividades
            .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => Grouping.Create(
                nombreEmpleado, actividadesEmpleado))
            .OrderBy(a => a.Key)))
    .OrderBy(a => a.Key);

答案 2 :(得分:0)

你不能在方法之间传递匿名类型;如果需要将数据传递给另一个方法,则需要创建包含ActividadesNombreEmpleado属性的显式命名类型,以及另一个包含FechaFechaActividades的属性