Yar*_*rik 8 c# linq lambda expression
我有代码只使用一个属性"名称"构建列表.如何修改代码,以便它可以构建具有两个属性"Name"和"Test_Result"的列表我知道匿名类型可以用来执行此操作,但是如何将它们用于动态表达式?这是我的代码:
string item = "Name";
string item2 = "Test_Result";
Type studentType = typeof(Student);
ParameterExpression itemParam = Expression.Parameter(studentType, item);
MemberInfo itemProperty = studentType.GetProperty(item);
MemberExpression valueInItemField = 
    Expression.MakeMemberAccess(itemParam, itemProperty);
Expression<Func<Student, string>> selectExpression =
    Expression<Func<Student, string>>
        .Lambda<Func<Student, string>>(valueInItemField, itemParam);
IEnumerable<string> currentItemFields = 
    DeserializedStudents.Select(selectExpression.Compile());
Run Code Online (Sandbox Code Playgroud)
    Mar*_*ell 27
我假设这里的"名称"和"Test_Result"是灵活的,不能硬编码.
匿名类型是完全定义的常规类; 关于它们唯一有趣的事情是编译器提供的细节而不是你.
我建议,处理这种情况的方法是使用Tuple.Create创建IEnumerable<Tuple<string,string>>和称它们为Item1,Item2从(名字Tuple<,>.另一个选择是使用像ExpandoObject,然后请使用IDictionary<string,object>API或dynamicAPI,以把价值拿回来.
例如:
string item1 = "Name";
string item2 = "Test_Result";
Type studentType = typeof(Student);
var itemParam = Expression.Parameter(studentType, "x");
var member1 = Expression.PropertyOrField(itemParam, item1);
var member2 = Expression.PropertyOrField(itemParam, item2);
var selector = Expression.Call(typeof(Tuple), "Create",
    new[] { member1.Type, member2.Type }, member1, member2);
var lambda = Expression.Lambda<Func<Student, Tuple<string,string>>>(
    selector, itemParam);
var currentItemFields = students.Select(lambda.Compile());
Run Code Online (Sandbox Code Playgroud)
这是同样的投影与成员的自定义类型name和result:
class ProjectedData
{
    public string name { get; set; }
    public string result { get; set; }
}
...
string item1 = "Name";
string item2 = "Test_Result";
Type studentType = typeof(Student);
var itemParam = Expression.Parameter(studentType, "x");
var member1 = Expression.PropertyOrField(itemParam, item1);
var member2 = Expression.PropertyOrField(itemParam, item2);
var selector = Expression.MemberInit(Expression.New(typeof(ProjectedData)),
    Expression.Bind(typeof(ProjectedData).GetMember("name").Single(), member1),
    Expression.Bind(typeof(ProjectedData).GetMember("result").Single(), member2)
);
var lambda = Expression.Lambda<Func<Student, ProjectedData>>(
    selector, itemParam);
var currentItemFields = students.Select(lambda.Compile());
Run Code Online (Sandbox Code Playgroud)
或者对于使用字典的方法:
string[] fields = {"Name", "Test_Result"};
Type studentType = typeof(Student);
var itemParam = Expression.Parameter(studentType, "x");
var addMethod = typeof(Dictionary<string, object>).GetMethod(
    "Add", new[] { typeof(string), typeof(object) });
var selector = Expression.ListInit(
        Expression.New(typeof(Dictionary<string,object>)),
        fields.Select(field => Expression.ElementInit(addMethod,
            Expression.Constant(field),
            Expression.Convert(
                Expression.PropertyOrField(itemParam, field),
                typeof(object)
            )
        )));
var lambda = Expression.Lambda<Func<Student, Dictionary<string,object>>>(
    selector, itemParam);
var currentItemFields = students.Select(lambda.Compile());
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           5467 次  |  
        
|   最近记录:  |