创建表达式<func <tentity,object>&gt;动态调用Aggregate到IQueryable <tentity>

时间:2015-06-04 16:05:01

标签: c# generics dynamic delegates expression

我想创建一个Expression<Func<TEntity, object>>,以便稍后将其作为参数传递。

如果我使用以下功能创建它......

public Expression<Func<TEntity, object>> GetInclude(string property)
{
    ParameterExpression parameter = System.Linq.Expressions.Expression.Parameter(typeof(TEntity));
    System.Linq.Expressions.Expression ppty = System.Linq.Expressions.Expression.Property(parameter, property);
    LambdaExpression lambda = System.Linq.Expressions.Expression.Lambda(ppty, parameter);

    return (Expression<Func<TEntity, object>>)lambda;
}

...我在运行时遇到错误,试图返回结果,说该类型无法转换为对象。例如,如果TEntityPurchases,我希望通过提供Purchases.Customers作为参数来获取"Customers"

另一方面,如果我将这个功能变成通用的......

public Expression<Func<TEntity, TDest>> GetInclude<TDest>(string property) where TDest: class, new()
{
        ParameterExpression parameter = System.Linq.Expressions.Expression.Parameter(typeof(TEntity));
        System.Linq.Expressions.Expression ppty = System.Linq.Expressions.Expression.Property(parameter, property);
        LambdaExpression lambda = System.Linq.Expressions.Expression.Lambda(ppty, parameter);

        return (Expression<Func<TEntity, TDest>>)lambda;
}

...并从Generic Method中调用它......

MethodInfo methodInfoInclude = EntityRepository.GetMethod("GetInclude");
object[] parametersToIncludeArray = new object[] { "Customers" };  //For testing

//Get the type of object to be obtained:
Assembly Data = Assembly.Load("Domain.Entities");
Type EntityTypeReferenced = Data.GetTypes()
.Where(t => t.IsClass && t.Namespace == "Domain.Entities" && t.Name == "Customers") //For testing
.ToList<Type>().First();

MethodInfo methodInfoGenericInclude = methodInfoInclude.MakeGenericMethod(EntityTypeReferenced);
object include = methodInfoGenericInclude.Invoke(EntityRepositoryInstance, parametersToIncludeArray);

...我没有错误,我可以获得include对象。但是,当我调用需要Expression<Func<TEntity, object>>作为参数的方法时:

        object[] Includes = { include };

        MethodInfo methodInfo = EntityRepository.GetMethod("GetElementsWithInclude");
        object[] parametersToIncludeFunctionArray = new object[] { Includes };
        object Data = methodInfo.Invoke(EntityRepositoryInstance, parametersToIncludeFunctionArray);

......有类似......

public List<TEntity> GetElementsWithInclude(Expression<Func<TEntity,object>>[] Includes)
{
    return this.ApplyIncludes(this._Context.CreateDbSet<TEntity>(), Includes).AsEnumerable<TEntity>().ToList();
}

...我收到的错误如object[]无法转换为Expression<Func<TEntity,object>>[]

目标是像这样调用函数ApplyIncludes,动态创建表达式:

private IQueryable<TEntity> ApplyIncludes(IDbSet<TEntity> Entities, Expression<Func<TEntity, object>>[] Includes)
{
    return Includes.Aggregate(Entities.AsQueryable<TEntity>(),
        (Entity, Include) => Entity.Include(
            ((MemberExpression)Include.Body).Member.DeclaringType.Equals(typeof(TEntity)) ?
            ((MemberExpression)Include.Body).Member.Name :
            Include.Body.ToString().Replace(Include.Parameters[0].Name + ".", "").Replace("FirstOrDefault().", "")
            ));
}

对此有任何帮助,请???

非常感谢你。

1 个答案:

答案 0 :(得分:0)

试试这个函数,它还能验证要包含的属性是否确实存在。

public static Expression<Func<TEntity, object>> BuildIncludeExpression(string include)
{

    var entityType = typeof(TEntity);
    var propertyInfo = entityType.GetProperty(include); 
    if (propertyInfo == null) 
        throw new Exception("Unknown property");

    var parameter = Expression.Parameter(entityType);
    var property = Expression.Property(parameter, include);
    
    return Expression.Lambda<Func<TEntity, object>>(property, parameter);
}