[英]C# LINQ build expression with anonymous type
I have code which builds list only with one property "Name". 我有代码只使用一个属性“名称”构建列表。 How to modify the code so it can build list with two properties "Name" and "Test_Result" I know that anonymous type can be used to perform this, but how to put them to dynamic expression? 如何修改代码,以便它可以构建具有两个属性“Name”和“Test_Result”的列表我知道匿名类型可以用来执行此操作,但是如何将它们用于动态表达式? here is my code: 这是我的代码:
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());
I'm assuming that the "Name" and "Test_Result" here are flexible and cannot be hard-coded. 我假设这里的“名称”和“Test_Result”是灵活的,不能硬编码。
Anonymous types are fully defined regular classes; 匿名类型是完全定义的常规类; the only interesting thing about them is that the compiler provides the details instead of you. 关于它们唯一有趣的事情是编译器提供的细节而不是你。
I would suggest that the way to handle this scenario would be to use Tuple.Create
to create an IEnumerable<Tuple<string,string>>
and refer to them as Item1
, Item2
(the names from Tuple<,>
. The other option would be to use something like ExpandoObject
, and then use either the IDictionary<string,object>
API, or the dynamic
API, to get the values back out. 我建议处理这种情况的方法是使用Tuple.Create
创建一个IEnumerable<Tuple<string,string>>
并将它们称为Item1
, Item2
(来自Tuple<,>
的名称。另一个选项是使用像ExpandoObject
这样的东西,然后使用IDictionary<string,object>
API或dynamic
API来获取值。
For example: 例如:
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());
Here's the same projecting into a custom type with members name
and result
: 这是投射到具有成员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());
Or for the approach using a dictionary: 或者对于使用字典的方法:
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());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.