如何使用表达式树创建以下内容?
假设claims
是IQueryable
ClaimData
var lastNames = claims.Select(p1 => p1.Advisors.Select(p2 => p2.LastName));
示例类如下:
public class ClaimData
{
public string name { get; set; }
public IQueryable<AdvisorData> Advisors { get; set; }
public IQueryable<ActionData> Actions { get; set; }
}
public class AdvisorData
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class ActionData
{
public string Name { get; set; }
public string Comment { get; set; }
}
假设我们不知道ClaimData的哪个属性(本例中的Advisors)或者我们想要选择哪个属性(本例中为LastName)。
我想创建选择器但是有困难。这是我尝试过的代码,但是不完整,我显然感到困惑
var property = typeof(ClaimData).GetProperties().Where(p =>
{
var args = p.PropertyType.GetGenericArguments();
if (args.Count() == 0) return false;
var innerProperty = args.First().GetProperties().Where(pi => PropertyByAttributeFunc(pi, table, column));
return innerProperty.Count() > 0;
}).First();
var parameterExp = Expression.Parameter(typeof(ClaimData), "p1");
var propertyExp = Expression.Property(parameterExp, property.Name);
var propertyType = property.PropertyType.GenericTypeArguments.First();
var parameterInnerExp = Expression.Parameter(propertyType, "p2");
var propertyInner = propertyType.GetProperties().Where(pi => PropertyByAttributeFunc(pi, table, column)).First();
var propertyInnerExp = Expression.Property(parameterInnerExp, propertyInner.Name);
var selectMethod = typeof(Queryable).GetMethods().Where(x => x.Name == "Select").First()
.MakeGenericMethod(property.PropertyType, typeof(string));
var genericFunc = typeof(Func<,>).MakeGenericType(property.PropertyType, typeof(string));
var genericInnerFunc = typeof(Func<,>).MakeGenericType(propertyType, typeof(string));
var innerLambda = Expression.Lambda(genericInnerFunc, propertyInnerExp, parameterInnerExp);
var expCall = Expression.Call(selectMethod, propertyExp, innerLambda);
不要担心这一行:
var propertyInner = propertyType.GetProperties().Where(pi => PropertyByAttributeFunc(pi, table, column)).First();
它只为我返回正确的属性。
由于
答案 0 :(得分:1)
您的错误位于以下行:
var selectMethod = typeof(Queryable).GetMethods()
.Where(x => x.Name == "Select").First()
.MakeGenericMethod(property.PropertyType, typeof(string));
property.PropertyType
是IQueryable<AdvisorData>
。应该是AdvisorData
。 Select
的第一个通用参数是在查询中查找一个项的类型,而不是整个IQueryable
的类型。这意味着您的Select
来电需要传递IQueryable<IQueryable<AdvisorData>>
以匹配参数Select
预期。
变化很简单:
var selectMethod = typeof(Queryable).GetMethods()
.Where(x => x.Name == "Select").First()
.MakeGenericMethod(property.PropertyType.GetGenericArguments()[0],
typeof(string));