具有匿名类型的C#LINQ构建表达式

我有代码只使用一个属性“名称”构建列表。 如何修改代码,以便它可以构建具有两个属性“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> selectExpression = Expression<Func> .Lambda<Func>(valueInItemField, itemParam); IEnumerable currentItemFields = DeserializedStudents.Select(selectExpression.Compile()); 

我假设这里的“名称”和“Test_Result”是灵活的,不能硬编码。

匿名类型是完全定义的常规类; 关于它们唯一有趣的事情是编译器提供的细节而不是你。

我建议处理这种情况的方法是使用Tuple.Create创建一个IEnumerable>并将它们称为Item1Item2 (来自Tuple<,>的名称。另一个选项是使用像ExpandoObject这样的东西,然后使用IDictionary API或dynamic API来获取值。

例如:

 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>>( selector, itemParam); var currentItemFields = students.Select(lambda.Compile()); 

这是投射到具有成员nameresult的自定义类型的相同内容:

 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>( selector, itemParam); var currentItemFields = students.Select(lambda.Compile()); 

或者对于使用字典的方法:

 string[] fields = {"Name", "Test_Result"}; Type studentType = typeof(Student); var itemParam = Expression.Parameter(studentType, "x"); var addMethod = typeof(Dictionary).GetMethod( "Add", new[] { typeof(string), typeof(object) }); var selector = Expression.ListInit( Expression.New(typeof(Dictionary)), fields.Select(field => Expression.ElementInit(addMethod, Expression.Constant(field), Expression.Convert( Expression.PropertyOrField(itemParam, field), typeof(object) ) ))); var lambda = Expression.Lambda>>( selector, itemParam); var currentItemFields = students.Select(lambda.Compile());