【发布时间】:2021-05-25 13:32:25
【问题描述】:
问题和Dynamically generate LINQ select with nested properties很相似
public static Expression<Func<TSource, TTarget>> BuildSelector<TSource, TTarget>(string members) =>
BuildSelector<TSource, TTarget>(members.Split(',').Select(m => m.Trim()));
public static Expression<Func<TSource, TTarget>> BuildSelector<TSource, TTarget>(IEnumerable<string> members)
{
var parameter = Expression.Parameter(typeof(TSource), "e");
var body = NewObject(typeof(TTarget), parameter, members.Select(m => m.Split('.')));
return Expression.Lambda<Func<TSource, TTarget>>(body, parameter);
}
static Expression NewObject(Type targetType, Expression source, IEnumerable<string[]> memberPaths, int depth = 0)
{
var bindings = new List<MemberBinding>();
var target = Expression.Constant(null, targetType);
foreach (var memberGroup in memberPaths.GroupBy(path => path[depth]))
{
var memberName = memberGroup.Key;
var targetMember = Expression.PropertyOrField(target, memberName);
var sourceMember = Expression.PropertyOrField(source, memberName);
var childMembers = memberGroup.Where(path => depth + 1 < path.Length);
var targetValue = !childMembers.Any() ? sourceMember :
NewObject(targetMember.Type, sourceMember, childMembers, depth + 1);
bindings.Add(Expression.Bind(targetMember.Member, targetValue));
}
return Expression.MemberInit(Expression.New(targetType), bindings);
}
Ivan Stoev 提供的不错的通用解决方案工作正常,但问题是它不支持 collection 属性。
例如,source.Property1.Property2 - 如果 Property1 是用户集合,则代码不起作用,因为 Property2 不是集合的属性,但属于 Property1 类型。
class Shipment {
// other fields...
public int Id;
public Address Sender;
public List<Address> Recipients;
}
class Address {
public string AddressText;
public string CityName;
public string CityId;
}
上面的类和代码我可以查询
var test = BuildSelector<Shipment, Shipment>(
"Id, Sender.CityId, Sender.CityName");
但如果我只想获取收件人的城市名称,我不能执行以下操作(因为收件人是集合):
var test = BuildSelector<Shipment, Shipment>(
"Recipients.CityName");
我是 C# 表达式的新手,不知道如何改进上述解决方案以使其适用于集合属性。
【问题讨论】:
-
添加示例类以及您打算如何使用。
-
已添加。谢谢。
标签: c# linq select expression linq-expressions