如何使用 LINQ select 动态列表中的特定字段
How to select specific fields from dynamic list using LINQ
我试图从动态对象中获取一些特定的字段,实际上是任何 class 的列表,这个 class 包含我想要的那些字段中的各种字段 select 使用 LINQ 的一些特定字段,我想要 select 的字段也由用户传递。下面是我尝试使用 System.Linq.Dynamic.
的代码
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Linq.Dynamic;
using System.Collections;
private void Test_Click(object sender, EventArgs e)
{
List<RateInfo> lst = new List<RateInfo>();
lst.Add(new RateInfo() { id_country = "IND", id_state = 1, rate = 2.3f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 2, rate = 1.1f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 3, rate = 5.2f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 4, rate = 6.5f });
GetDynamicData(lst, new List<string>() { "id_country", "id_state" });
}
private void GetDynamicData(dynamic list, List<string> fetchFields)
{
var data = ((IEnumerable)list).Cast<dynamic>()
.Select(r => new { r }).AsQueryable();
StringBuilder s = new StringBuilder();
//This is for test only.
//It works, the value of "id_state" and "id_state" getting appended
foreach (var item in data)
{
s.Append(item.r.id_state);
s.Append(",");
s.Append(item.r.id_country);
}
//-----------------------------------------------------
//Select the specific field data from dynamic list
StringBuilder fields = new StringBuilder();
fields.Append("new (");
foreach (var fld in fetchFields)
{
fields.Append("r." + fld);
fields.Append(",");
}
fields.Remove(fields.Length - 1, 1);
fields.Append(")");
//This does not work throws error
//"No property or field 'id_country' exists in type 'Object'"
IQueryable iq = data.Select(fields.ToString());
//For test only to check the value of selected fields
foreach (dynamic item in iq)
{
s.Append(item.id_state);
s.Append(",");
s.Append(item.id_country);
}
}
您应该尝试使用 generics:
private void GetDynamicData<T>(IEnumerable<T> list, List<string> fetchFields)
{
var data = list.AsQueryable();
您可以大大简化您的 GetDynamicData
方法,同时指定显式列表类型 (GetDynamicData(IList<RateInfo> list, ...)
) 并保留列表项类型通用,以便重用该方法;考虑到最后一种方法,您可以按如下方式重写 GetDynamicData
,以获得所需的输出:
private void GetDynamicData<T>(IEnumerable<T> list, List<string> fetchFields)
{
var fields = $"new ({string.Join(",", fetchFields)})";
var res = list.AsQueryable().Select(fields);
//For test only to check the value of selected fields
foreach (dynamic item in res) {
Console.WriteLine(item.id_state);
Console.WriteLine(item.id_country);
}
}
输出
1
IND
2
IND
3
IND
4
IND
说明
我认为区别在于明确指定类型(通过泛型 T
或通过 RateInfo
)强制 LINQ 知道列表项的类型;如果您使用 dynamic
,IQuqryable
实例的 IQueryable.ElementType
的值为 System.Object
,则查询失败并出现您遇到的错误。
我试图从动态对象中获取一些特定的字段,实际上是任何 class 的列表,这个 class 包含我想要的那些字段中的各种字段 select 使用 LINQ 的一些特定字段,我想要 select 的字段也由用户传递。下面是我尝试使用 System.Linq.Dynamic.
的代码using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Linq.Dynamic;
using System.Collections;
private void Test_Click(object sender, EventArgs e)
{
List<RateInfo> lst = new List<RateInfo>();
lst.Add(new RateInfo() { id_country = "IND", id_state = 1, rate = 2.3f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 2, rate = 1.1f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 3, rate = 5.2f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 4, rate = 6.5f });
GetDynamicData(lst, new List<string>() { "id_country", "id_state" });
}
private void GetDynamicData(dynamic list, List<string> fetchFields)
{
var data = ((IEnumerable)list).Cast<dynamic>()
.Select(r => new { r }).AsQueryable();
StringBuilder s = new StringBuilder();
//This is for test only.
//It works, the value of "id_state" and "id_state" getting appended
foreach (var item in data)
{
s.Append(item.r.id_state);
s.Append(",");
s.Append(item.r.id_country);
}
//-----------------------------------------------------
//Select the specific field data from dynamic list
StringBuilder fields = new StringBuilder();
fields.Append("new (");
foreach (var fld in fetchFields)
{
fields.Append("r." + fld);
fields.Append(",");
}
fields.Remove(fields.Length - 1, 1);
fields.Append(")");
//This does not work throws error
//"No property or field 'id_country' exists in type 'Object'"
IQueryable iq = data.Select(fields.ToString());
//For test only to check the value of selected fields
foreach (dynamic item in iq)
{
s.Append(item.id_state);
s.Append(",");
s.Append(item.id_country);
}
}
您应该尝试使用 generics:
private void GetDynamicData<T>(IEnumerable<T> list, List<string> fetchFields)
{
var data = list.AsQueryable();
您可以大大简化您的 GetDynamicData
方法,同时指定显式列表类型 (GetDynamicData(IList<RateInfo> list, ...)
) 并保留列表项类型通用,以便重用该方法;考虑到最后一种方法,您可以按如下方式重写 GetDynamicData
,以获得所需的输出:
private void GetDynamicData<T>(IEnumerable<T> list, List<string> fetchFields)
{
var fields = $"new ({string.Join(",", fetchFields)})";
var res = list.AsQueryable().Select(fields);
//For test only to check the value of selected fields
foreach (dynamic item in res) {
Console.WriteLine(item.id_state);
Console.WriteLine(item.id_country);
}
}
输出
1
IND
2
IND
3
IND
4
IND
说明
我认为区别在于明确指定类型(通过泛型 T
或通过 RateInfo
)强制 LINQ 知道列表项的类型;如果您使用 dynamic
,IQuqryable
实例的 IQueryable.ElementType
的值为 System.Object
,则查询失败并出现您遇到的错误。