【问题标题】:Create select within select in expression tree在表达式树的选择中创建选择
【发布时间】:2014-11-25 18:39:41
【问题描述】:

如何使用表达式树创建以下内容? 假设claimsIQueryableClaimData

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 的哪个属性(本例中为顾问)或该属性(本例中为 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();

它只是为我返回正确的属性。

谢谢

【问题讨论】:

    标签: c# reflection lambda expression-trees


    【解决方案1】:

    您的错误出现在以下行:

    var selectMethod = typeof(Queryable).GetMethods()
        .Where(x => x.Name == "Select").First()
        .MakeGenericMethod(property.PropertyType, typeof(string));
    

    property.PropertyTypeIQueryable&lt;AdvisorData&gt;。它应该只是AdvisorDataSelect 的第一个通用参数是在查询中查找 一个项目 的类型,而不是整个 IQueryable 的类型。这意味着您的Select 调用需要传入IQueryable&lt;IQueryable&lt;AdvisorData&gt;&gt; 以匹配Select 期望的参数。

    改变很简单:

    var selectMethod = typeof(Queryable).GetMethods()
        .Where(x => x.Name == "Select").First()
        .MakeGenericMethod(property.PropertyType.GetGenericArguments()[0], 
            typeof(string));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-25
      • 2015-09-12
      • 2010-10-11
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多