与匿名类型C#LINQ构建表达 [英] C# LINQ build expression with anonymous type

查看:148
本文介绍了与匿名类型C#LINQ构建表达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有代码,建立仅列出一个名称属性。
如何修改代码,以便它可以具有两个属性名称和Test_Result
我知道,匿名类型可以用来执行这一点,但如何将它们投入到动态表情建名单?这里
是我的代码:

 字符串项=姓名; 
串ITEM2 =Test_Result;
型studentType = typeof运算(学生);

ParameterExpression itemParam = Expression.Parameter(studentType,项目);
的MemberInfo itemProperty = studentType.GetProperty(项目);

MemberExpression valueInItemField =
Expression.MakeMemberAccess(itemParam,itemProperty);

表达式来; Func键<学生,串>> selectExpression =
表达式来; Func键<学生,串>>
.Lambda<&Func键LT;学生,串>>(valueInItemField,itemParam);

IEnumerable的<串GT; currentItemFields =
DeserializedStudents.Select(selectExpression.Compile());


解决方案

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



匿名类型完全定义普通班;关于他们的唯一有趣的事情是,编译的提供的细节,而不是你。



我建议,处理这种事情的场景方式是使用 Tuple.Create 来创建一个的IEnumerable<元组LT;字符串,字符串>> ,并把它们称作项目1 项目2 (从姓名元组LT;,> 另一种选择是使用像 ExpandoObject ,然后请使用的IDictionary<字符串对象> 。API,或动态 API,以获取值退了出去。



例如:

 字符串ITEM1 =姓名; 
串ITEM2 =Test_Result;
型studentType = typeof运算(学生);

变种itemParam = Expression.Parameter(studentType,×);
变种的member1 = Expression.PropertyOrField(itemParam,ITEM1);
变种member2 = Expression.PropertyOrField(itemParam, ITEM2);
VAR选择= Expression.Call(typeof运算(元组),创建,
新的[] {m​​ember1.Type,member2.Type}的member1,member2);
VAR波长= Expression.Lambda<&Func键LT;学生,元组LT;字符串,字符串>>>(
选择,itemParam);

变种currentItemFields = students.Select(lambda.Compile());






下面是同样的投影与会员自定义类型名称结果

 类ProjectedData 
{
公共字符串名称{;组; }
公共字符串结果{搞定;组; }
}

...

串ITEM1 =姓名;
串ITEM2 =Test_Result;
型studentType = typeof运算(学生);

变种itemParam = Expression.Parameter(studentType,×);
变种的member1 = Expression.PropertyOrField(itemParam,ITEM1);
VAR member2 = Expression.PropertyOrField(itemParam,ITEM2);
VAR选择= Expression.MemberInit(Expression.New(typeof运算(ProjectedData)),
Expression.Bind(typeof运算(ProjectedData).GetMember(名)。单()的member1),
Expression.Bind(typeof运算(ProjectedData).GetMember(结果)单(),member2。)
);
VAR波长= Expression.Lambda<&Func键LT;学生,ProjectedData>>(
选择,itemParam);

变种currentItemFields = students.Select(lambda.Compile());






或为使用字典的方式:

 的String []栏= {姓名,Test_Result}; 
型studentType = typeof运算(学生);

变种itemParam = Expression.Parameter(studentType,×);

VAR addMethod = typeof运算(字典<字符串对象>)。实现getMethod(
添加,新的[] {typeof运算(字符串)的typeof(对象)});
VAR选择= Expression.ListInit(
Expression.New(typeof运算(字典<字符串对象>)),
fields.Select(字段=> Expression.ElementInit(addMethod,
Expression.Constant(场),
Expression.Convert(
Expression.PropertyOrField(itemParam,场),
的typeof(对象)

))) ;
VAR波长= Expression.Lambda<&Func键LT;学生,字典<字符串对象>>>(
选择,itemParam);

变种currentItemFields = students.Select(lambda.Compile());


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? 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.

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.

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:

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());

这篇关于与匿名类型C#LINQ构建表达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆