按多个键查找条目

时间:2014-09-08 12:02:14

标签: c# sql linq expression repository-pattern

修改

为了进一步说明,在下面的示例中,通过使用反射来构建表达式树,以确定相关属性的名称。因为我有" T"定义为类泛型并已限制在某个接口,我正在寻找强类型方法。这应该是IMO。

期望的结果

public class RepositoryBase<TEntity, TKey> : IRepository<TEntity, TKey>
    where TEntity : IEntity<TKey>
{

    protected virtual ISpecification<TEntity> ByMultipleKeysSpecification(IEnumerable<TKey> keys)
    {
        return keys.Select(key =>
            Expression.Lambda<Func<TEntity, bool>>(entity => key.Equals(entity.Id)))
            .Aggregate<Expression<Func<TEntity, bool>>, ISpecification<TEntity>>(null,
                (current, lambda) => current == null ? new ExpressionSpecification<TEntity>(lambda) : current.Or(lambda)
            );      
    }

}

我正在寻找一种方法来创建一个通过多个键查找实体的规范。我已经在网上找到了这个例子:

keys.Select(key =>
                Expression.Lambda<Func<T, bool>>(
                    Expression.Equal(
                        Expression.PropertyOrField(parameter, propInfo.Name),
                        Expression.Constant(key)
                    ), parameter
                )
            )
            .Aggregate<Expression<Func<T, bool>>, ISpecification<T>>(null,
                (current, lambda) => current == null ? new Specification<T>(lambda) : current.Or(lambda)
            );

这个示例接近我的需要,但是它在运行时使用反射来评估 id 属性的名称,因为任何类型都可以用作 T 。在我的例子中,我将可能的类型限制为自定义接口( IEntity ),因此* id *属性在编译时是已知的。我如何重构示例以满足我的需求?我不认为有必要在运行时创建表达式在运行时评估属性。

1 个答案:

答案 0 :(得分:1)

我不确定我理解你在寻找什么,但如果我说得对,你需要做的就是在Select电话中将你的表达式转换为正确的类型。这将告诉编译器在编译时将其视为表达式,因此您不需要在运行时构建它。

protected virtual ISpecification<TEntity> ByMultipleKeysSpecification(IEnumerable<TKey> keys) 
{
    return keys.Select(key => (Expression<Func<TEntity, bool>>)(entity => key.Equals(entity.Id)))
        .Aggregate<Expression<Func<TEntity, bool>>, ISpecification<TEntity>>(null,
            (current, lambda) => current == null ? new Specification<TEntity>(lambda) : current.Or(lambda)
        );
}