2010-11-17 58 views
0

如何在下面的DoIt函数中查询其中一个新属性的值?从LINQ查询中获取值

public object GetData() 
{ 
     var table = GetDataTable(); 
     var view = table.DefaultView; 
     //..... more code 
     var query = from row in view.ToTable().AsEnumerable() 
        group row by row.Field<string>("ShortName") into grouping 
        select new 
         { 
          ShortName = grouping.Key, 
          SCount = grouping.Sum(count => count.Field<int>("ProfCount")), 
          DisplayText = string.Empty 
         }; 
     return query; 
} 

// this code doesn't work 
public void DoIt() 
{ 
    var result = GetData(); 
    string shortName = result.ShortName; 
} 

谢谢!

回答

2

你返回一个匿名类型(通过选择新的{}),这是只有在局部范围内有效。你需要创建一个具体类型并从你的函数而不是对象中返回。

public SomeClass GetData() 
{ 
     var table = GetDataTable(); 
     var view = table.DefaultView; 
     //..... more code 
     var query = from row in view.ToTable().AsEnumerable() 
        group row by row.Field<string>("ShortName") into grouping 
        select new SomeClass 
         { 
          ShortName = grouping.Key, 
          SCount = grouping.Sum(count => count.Field<int>("ProfCount")), 
          DisplayText = string.Empty 
         }; 
     return query; 
} 

// this code doesn't work 
public void DoIt() 
{ 
    var result = GetData(); 
    string shortName = result.ShortName; 
} 

public class SomeClass 
{ 
    public string ShortName { get; set; } 
    public int SCount { get; set; } 
    public string DisplayText { get; set; } 
} 
+0

可以使用现有的类型吗?我宁愿在这里使用数据列。 – 2010-11-17 17:54:24

+1

您绝对可以使用现有的类型。你不能在局部范围外使用匿名类型。你只需要一个公开可见的类型,因为你从公共方法返回它。 (如果方法是私有的,显式类型可以是私有嵌套类。) – 2010-11-17 17:56:07

+1

@James Kovacs:“你不能在局部范围外使用匿名类型。”这是错误的(是的,MSDN上有这样的错误陈述)。 – jason 2010-11-17 18:02:55

4

匿名类型不会被称为匿名类型。所以:

定义类型与名称(代码6个其他行):

public class Foo 
{ 
    public string ShortName { get; set; } 
    public int SCount { get; set; } 
    public string DisplayText { get; set; } 
} 

现在修改GetData签名(代码0其他行):

public IEnumerable<Foo> GetData() 

和你LINQ查询到(3个附加字符,或者如果您选择更有意义的名称,则更多):

var query = 
    from row in view.ToTable().AsEnumerable() 
    group row by row.Field<string>("ShortName") into grouping 
    select new Foo 
    { 
     ShortName = grouping.Key, 
     SCount = grouping.Sum(count => count.Field<int>("ProfCount")), 
     DisplayText = string.Empty 
    }; 
+1

的GetData将返回一个IEnumerable ,而不只是富。 – 2010-11-17 17:51:45

+0

@Etienne de Martel,找到了我。编辑:-) – 2010-11-17 17:52:25

0

你不能没有使用反射。由于它是匿名类型,因此无法在DoIt()方法中强制转换为类型名称,因为在编译时不知道类型名称。

1

嗯,DoIt不知道result有一个名为ShortName的属性,因为它的类型为object。您可以创建一个具体的类来保存结果,使用反射或使用dynamic。请注意,无论哪种方式,GetData确实会返回IEnumerable<T>,其中T目前是匿名类型。

使用具体类:

public class Foo { 
    public string ShortName { get; set; } 
    public int SCount { get; set; } 
    public string DisplayText { get; set; } 
} 

public IEnumerable<Foo> GetData() { 
    var table = GetDataTable(); 
    var view = table.DefaultView; 
    //..... more code 
    var query = from row in view.ToTable().AsEnumerable() 
       group row by row.Field<string>("ShortName") into grouping 
       select new Foo 
        { 
         ShortName = grouping.Key, 
         SCount = grouping.Sum(count => count.Field<int>("ProfCount")), 
         DisplayText = string.Empty 
        }; 
    return query; 
} 

public void DoIt() { 
    var result = GetData(); 
    foreach(var item in result) { 
     Console.WriteLine(item.ShortName); 
    } 
} 

使用反射:

public IEnumerable GetData() { 
    var table = GetDataTable(); 
    var view = table.DefaultView; 
    //..... more code 
    var query = from row in view.ToTable().AsEnumerable() 
       group row by row.Field<string>("ShortName") into grouping 
       select new Foo 
        { 
         ShortName = grouping.Key, 
         SCount = grouping.Sum(count => count.Field<int>("ProfCount")), 
         DisplayText = string.Empty 
        }; 
    return query; 
} 

public void DoIt() { 
    var result = GetData(); 
    PropertyInfo property = result.First().GetType().GetProperty("ShortName"); 
    foreach(var item in result) { 
     string shortName = property.GetValue(item, null); 
     Console.WriteLine(shortName); 
    } 
} 
0

这给了我什么,我需要:

public object GetData() 
{ 
     var table = GetDataTable(); 
     var view = table.DefaultView; 
     //..... more code 
      var query = from row in view.ToTable().AsEnumerable() 
        group row by row.Field<string>("ShortName") into grouping 
        select new Object[] 
         { 
          grouping.Key, 
          grouping.Sum(count => count.Field<int>("ProfCount")), 
          string.Empty 
         }; 
      return query; 
} 


public void DoIt() 
{ 
    // Note: Pretend that GetData returned only one result 
    object[] result = GetData() as object[]; 
    var shortName = result[0]; 
}