>,c#,linq,expression-trees"/>

首页 > 解决方案 > 动态 Linq 从列表中选择>

问题描述

考虑我有这个IQueryble类似于这个列表 List 和 linq 的数据库集合:

var lstData = new List<IDictionary<string, object>>()
{
   new Dictionary<string, object>() {
        { "Name" , "John"},
        { "Age", 20 },
        { "School", "Waterloo" }
    },
   new Dictionary<string, object>() {
        { "Name" , "Goli"},
        { "Age", 23 },
        { "School", "Mazandaran" }
    },
};    

var result = lstData.Select(x => new { Name= x["Name"], School= x["School"] });

但是,我不知道编译时的属性名称。如何在运行时动态选择 Linq 选择中的特定列?像这样的东西:

var result= lstData .Select("Name,School");

标签: c#linqexpression-trees

解决方案


我已经完成了代码,试试下面的代码。

Func<IDictionary<string, object>, dynamic> CreateDynamicFromDict(string fields)
{
     // input parameter "x"
     var xParameter = Expression.Parameter(typeof(IDictionary<string, object>), "x");
     // output object
     var result = Expression.Parameter(typeof(IDictionary<string, object>), "result");

     var add = typeof(IDictionary<string, object>).GetMethod("Add");

     var body = new List<Expression>();
     //initial output object
     body.Add(Expression.Assign(result, Expression.New(typeof(ExpandoObject))));

     // set value "FieldN = x.FieldN"
     var bindings = fields.Split(',').Select(o => o.Trim())
     .Select(o =>
     {
           var key = Expression.Constant(o);
           return Expression.Call(result, add, key, Expression.Property(xParameter, "Item", key));
     });

     body.AddRange(bindings);
     // return value
     body.Add(result);

     var block = Expression.Block(new[] { result }, body);

     var lambda = Expression.Lambda<Func<IDictionary<string, object>, dynamic>>(block, xParameter);

     // compile to Func<IDictionary<string, object>, dynamic>
     return lambda.Compile();
}

用法是

var result = lstData.Select(CreateDynamicFromDict("Field1, Field2"));

参考:

LINQ:动态选择

表达式树使用类的属性值创建字典

表达式树 (C#)

表达式树


推荐阅读