我想在我们的存储库中添加一个检查,用于过滤companyId上的所有对象(如果它在那里)并且它与给定值匹配。
所以我们有:
public T First<T>(Expression<Func<T, bool>> expression) where T : EntityObject
{
var set = GetObjectSet<T>();
return set.FirstOrDefault<T>();
}
我想添加看起来像......的线条
express.And("Check for CompanyId property if it exists then make sure it = 3");
关于如何解决这个问题的任何想法?
谢谢:)
答案 0 :(得分:4)
如果您正在寻找一个可以用来处理公司ID的函数,如果实体上存在公司ID,请检查您的表达式,这应该可以解决问题:
public static Expression<Func<T, bool>> CheckPropertyIfExists<T, TProperty>(Expression<Func<T, bool>> expression, string propertyName, TProperty propertyValue)
{
Type type = typeof(T);
var property = type.GetProperty(propertyName, typeof(TProperty));
if(property == null || !property.CanRead)
return expression;
return expression.Update(
Expression.And( // &&
Expression.Equal( // ==
Expression.MakeMemberAccess(expression.Parameters[0], property), // T parameter.{propertyName}
Expression.Constant(propertyValue) // specified propertyValue constant
),
expression.Body // Original expression
),
expression.Parameters
);
}
您可以像这样使用它:
public T First<T>(Expression<Func<T, bool>> expression, int companyId)
{
var set = GetObjectSet<T>();
return set.FirstOrDefault<T>(CheckPropertyIfExists(expression, "CompanyId", companyId));
}
现在,您可以使用您的表达式调用First
方法,并使用想要过滤的公司名称。
执行此操作的稍微好一点的方法可能是将其用作过滤方法,即将其重写为不需要内部表达式并处理对象查询(或IQueryable)的扩展方法:
public static ObjectQuery<T> FilterByPropertyIfExists<T, TProperty>(this ObjectQuery<T> query, string propertyName, TProperty propertyValue)
{
Type type = typeof(T);
var property = type.GetProperty(propertyName, typeof(TProperty));
if(property == null || !property.CanRead)
return query;
var parameter = Expression.Parameter(typeof(T), "x");
Expression<Func<T, bool>> predicate = (Expression<Func<T, bool>>)Expression.Lambda(
Expression.Equal( // ==
Expression.MakeMemberAccess(parameter, property), // T parameter.{propertyName}
Expression.Constant(propertyValue) // specified propertyValue constant
),
parameter
);
return query.Where(predicate);
}
这样做的好处在于它可以与标准LINQ语法(查询和流畅)完美配合。
e.g。它允许这样的查询:
from x in repository.Clients.FilterByPropertyIfExists("Company", 5)
where x == ???
select x.Name;
<强> [编辑] 强>
我已经清理了一下并添加了对参数可见性的检查(必须是公共的静态属性),以及ObjectQuery实现(它将自动用于ObjectQuery和ObjectSet):
public static class QueryExtensions
{
public static IQueryable<T> FilterByPropertyIfExists<T, TProperty>(this IQueryable<T> query, string propertyName, TProperty propertyValue)
{
Type type = typeof(T);
var property = type.GetProperty(
propertyName,
BindingFlags.Instance | BindingFlags.Public, // Must be a public instance property
null,
typeof(TProperty), // Must be of the correct return type
Type.EmptyTypes, // Can't have parameters
null
);
if (property == null || !property.CanRead) // Must exist and be readable
return query; // Return query unchanged
// Create a predicate to pass to the Where method
var parameter = Expression.Parameter(typeof(T), "it");
Expression<Func<T, bool>> predicate = (Expression<Func<T, bool>>)Expression.Lambda(
Expression.Equal( // ==
Expression.MakeMemberAccess(parameter, property), // T parameter.{propertyName}
Expression.Constant(propertyValue) // specified propertyValue constant
),
parameter
);
return query.Where(predicate); // Filter the query
}
public static ObjectQuery<T> FilterByPropertyIfExists<T, TProperty>(this ObjectQuery<T> query, string propertyName, TProperty propertyValue)
{
var filteredQuery = FilterByPropertyIfExists((IQueryable<T>)query, propertyName, propertyValue);
return (ObjectQuery<T>)filteredQuery; // Cast filtered query back to an ObjectQuery
}
}
答案 1 :(得分:1)
看起来像是一个很好的候选人,可以远离反思:
public interface ICompanyFilterable
{
int CompanyId { get; set; }
}
public partial class YourEntity : ICompanyFilterable
{
....
}
public static IQueryable<T> FilterByCompanyId<T>(this IQueryable<T> query, int companyId)
where T : ICompanyFilterable
{
return query.Where(e => e.CompanyId == companyId);
}
答案 2 :(得分:0)
Bennor, 非常感谢您的帖子非常有用。
我把你放在那里的东西创建了一个扩展方法,它将'And'过滤器附加到现有表达式。
public static Expression<Func<T, bool>> AddEqualityCheck<T, TProperty>(this Expression<Func<T, bool>> expression, string propertyName, TProperty propertyValue)
{
Type type = typeof(T);
var property = type.GetProperty(
propertyName,
BindingFlags.Instance | BindingFlags.Public,
null,
typeof(TProperty),
Type.EmptyTypes,
null
);
if (property == null || !property.CanRead)
{
return expression;
}
else
{
var equalityExpression = Expression.Equal(
Expression.MakeMemberAccess(expression.Parameters[0], property),
Expression.Constant(propertyValue)
);
var andEqualityExpression = Expression.And(equalityExpression, expression.Body);
return expression.Update(andEqualityExpression, expression.Parameters);
}
}