4

可能重复:
如何将匿名类型传递给方法?

我想将 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
4

3 回答 3

4

new { a, b, c, d, l }创建一个匿名类型的项目,因此整个 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);

请记住,LINQSelect()已延迟执行,因此在您访问结果集枚举之前​​不会执行查询本身,因此如果您需要立即执行它,只需.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 基础知识的人来说,它不是灵丹妙药。

于 2012-12-01T17:16:28.683 回答
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
}

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

于 2012-12-01T17:18:17.503 回答
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();

将在方法内生成项目的公共属性数组MethodResult image.

于 2012-12-01T17:31:40.350 回答