我如何将LINQ结果匿名类型传递给另一个方法?

时间:2012-12-01 17:06:16

标签: c# linq

  

可能重复:
  How can I pass an anonymous type to a method?

我想将LINQ结果的集合传递给另一个方法

这是LinQ代码

var sets =
        from a in patient
        from b in patient
        from c in patient
        from d in patient
        from l in patient
        where a.VisitNum < b.VisitNum && b.VisitNum < c.VisitNum && c.VisitNum < d.VisitNum && d.VisitNum < l.VisitNum
        select new { a, b, c, d, l };

查询显示的结果类似于“组合”

   ID    Visit DAte       Visit number    Rational 
    -------------------------------------------------
   a- 1     14/05/2011           1           new
   b- 1     15/06/2012           2           Emergency 
   c- 1     17/07/2012           3           Check-Up

   a- 1     14/05/2011           1           new
   b- 1     15/06/2012           2           Emergency 
   c- 1     18/12/2012           5           Check-Up

3 个答案:

答案 0 :(得分:4)

new { a, b, c, d, l }创建一个anonymous type项,因此整个LINQ查询的返回值也会以匿名类型返回。要在方法中传递这样的值,我建议将其转换为已知类型。如果您想从具体实现中抽象出一个方法,只需引入一个新类和一个接口:

不清楚查询的作用和属性类型,因此更新类和类型名称:

interface IResultSet
{
   TypeA A { get; }
   TypeB B { get; }
   TypeC C { get; }
   TypeD D { get; }
   TypeL L { get; }
}

class ResultSet : IResultSet
{
   public ResultSet(inject all property values here) {}

   public TypeA A { get; private set; }
   public TypeB B { get; private set; }
   public TypeC C { get; private set; }
   public TypeD D { get; private set; }
   public TypeL L { get; private set; }
}

IEnumerable<IResultSet> sets =
    from a in patient
    from b in patient
    from c in patient
    from d in patient
    from l in patient
    where a.VisitNum < b.VisitNum 
          && b.VisitNum < c.VisitNum 
          && c.VisitNum < d.VisitNum 
          && d.VisitNum < l.VisitNum
    select new ResultSet(a, b, c, d, l);

请记住,LINQ Select()已经确定了执行,因此在您访问结果集枚举之前​​,查询本身不会被执行,因此如果您需要立即执行它,只需在查询中添加.ToList()调用端:

递延:

ProcessData(sets);

立即执行:

ProcessData(sets.ToList());

// Now you can pass results in a method like this
public void ProcessData(IEnumerable<IResultSet> items)

最后我建议不要使用dynamic类型来抽象这样的匿名类型,你可以使用它,但在某些特殊情况下,这将是充分的决定。在你的情况下,它会降低代码的可读性并破坏类型安全性,dynamic完全适合DSL引擎和处理动态结构数据的东西,但对于那些非常了解OOP基础知识的人来说不是银弹。

答案 1 :(得分:1)

您无法直接将匿名类型传递给其他方法,因为解决方法很少:

首先,您可以通过dynamic参数传递它:

var at = new { a = 1, b = 2, c = 3, d = 4, l = 5 };
ProcessAnonymousType(at);

void ProcessAnonymousType(dynamic at)
{
  Console.WriteLine("Anonymous type data: {0}, {1}, {2}", at.a, at.b, at.c);
}

您可以通过对象传递匿名类型实例并使用反射来访问属性(实际上这与前一个非常相似,但需要您付出更多努力):

void ProcessAnonymousType(object at)
{
    // Use reflection to access a, b, c properties
}

而且,与往常一样,您可以使用命名类型。

答案 2 :(得分:0)

您可以传递类型参数(以及匿名类型),如下所示:

void Method<T>(T obj)
{
}

然后使用反射来提取存储在其中的所有公共属性。 任何非类型变量可以作为参数传递,如下所示:

var item = new { Foo = 1, Bar = "2" };
Method(item);

并且没有例外。 至于反射,这段代码

object[] values = typeof(T)
    .GetProperties(BindingFlags.Instance | BindingFlags.Public)
    .Select(W => W.GetValue(obj, null)).ToArray();

将在Method方法中生成项目的公共属性数组。 Result image