2010-11-17 77 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]; 
}