如何包含一个检查Property的And()表达式及其值 [英] How to include an And() Expression that checks for a Property and it's value

查看:125
本文介绍了如何包含一个检查Property的And()表达式及其值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我们的存储库中添加一个检查,用于在companyId上过滤所有对象,如果它在那里,并且匹配给定的值。



所以我们有:

  public T First< T> (表达式< Func< T,bool>>表达式)其中T:EntityObject 
{
var set = GetObjectSet< T>();
return set.FirstOrDefault< T>();
}

我想添加一些看起来像...

  express.And(检查CompanyId属性是否存在,然后确保它= 3); 

有关如何解决这个问题的任何想法?

谢谢:)


解决方案

如果您正在寻找一个功能,如果公司ID存在,您可以使用该功能来将公司id检查到您的表达式在实体上,这应该是诀窍:

  public static Expression&FunC< T,bool>> CheckPropertyIfExists< T,TProperty>(表达式< Func< T,bool>>表达式,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],属性),// T参数。{propertyName}
Expression.Constant(propertyValue)//指定propertyValue常量
),
expression.Body //原始表达式
),
expression.Parameters
);
}

您可以这样使用:

  public T First< T>(表达式< Func< T,bool>>>表达式,int companyId)
{
var set = GetObjectSet< ; T>();
return set.FirstOrDefault< T>(CheckPropertyIfExists(expression,CompanyId,companyId));
}

现在,您可以调用您的 First 方法与您的表达式和您要过滤的companyId。



一个稍微更好的方法是将其用作过滤方法,即将其重写为不需要内部表达式并可用于对象查询(或IQueryable)的扩展方法:

  public静态ObjectQuery< T> FilterByPropertyIfExists< T,TProperty>(此ObjectQuery&T;查询,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);
表达式< Func< T,bool>>> predicate =(Expression< Func< T,bool>)Expression.Lambda(
Expression.Equal(// ==
Expression.MakeMemberAccess(parameter,property),// T parameter。{propertyName }
Expression.Constant(propertyValue)//指定propertyValue常数
),
参数
);
return query.Where(predicate);
}

这样的美妙之处在于它会很好地与标准LINQ语法(查询和流畅)。



eg它允许这样的查询:

  from x in repository.Clients.FilterByPropertyIfExists(Company,5)
where x == ???
select x.Name;


$ b $我已经清理了一下,并添加了一个参数可见性检查(必须是一个公共的静态属性),以及一个ObjectQuery实现(将自动用于ObjectQuery和ObjectSet):

  public static class QueryExtensions 
{
public static IQueryable< T> FilterByPropertyIfExists< T,TProperty>(此IQueryable查询,string propertyName,TProperty propertyValue)
{
类型type = typeof(T);
var property = type.GetProperty(
propertyName,
BindingFlags.Instance | BindingFlags.Public,//必须是公共实例属性
null,
typeof(TProperty ),//必须是正确的返回类型
Type.EmptyTypes,//不能有参数
null
);
if(property == null ||!property.CanRead)//必须存在且可读
return query; //返回查询不变

//创建一个谓词传递给Where方法
var parameter = Expression.Parameter(typeof(T),it);
表达式< Func< T,bool>>> predicate =(Expression< Func< T,bool>)Expression.Lambda(
Expression.Equal(// ==
Expression.MakeMemberAccess(parameter,property),// T parameter。{propertyName }
Expression.Constant(propertyValue)//指定propertyValue常数
),
参数
);
return query.Where(predicate); //过滤查询
}

public static ObjectQuery< T> FilterByPropertyIfExists< T,TProperty>(此ObjectQuery&T;查询,string propertyName,TProperty propertyValue)
{
var filteredQuery = FilterByPropertyIfExists((IQueryable ))查询,propertyName,propertyValue);
return(ObjectQuery< T>)filteredQuery; //将已过滤的查询转换为ObjectQuery
}
}


I'd like to add a check in our repository that filters all objects out on a companyId if it's there and if it matches a given value.

So where we have:

public T First<T>(Expression<Func<T, bool>> expression) where T : EntityObject  
{  
   var set = GetObjectSet<T>();  
   return set.FirstOrDefault<T>();  
}  

I would like to add line which looks something where...

express.And("Check for CompanyId property if it exists then make sure it = 3");  

Any ideas on how to go about this?
Thanks :)

解决方案

If you're looking for a function which you can use to tack on a company id check to your expression if a company id exists on the entity, this should do the trick:

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
    );
}

You could use it like this:

public T First<T>(Expression<Func<T, bool>> expression, int companyId)
{
    var set = GetObjectSet<T>();  
    return set.FirstOrDefault<T>(CheckPropertyIfExists(expression, "CompanyId", companyId));  
}

And now you can call your First method with your expression and the companyId you want to filter by.

A slightly better way to do this might be to use it as a filtering method, i.e. rewrite it as an extension method that doesn't require an inner expression and works on an object query (or 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);
}

The beauty of this is that it will work really nicely with the stanard LINQ syntaxes (both query and fluent).

e.g. it allows queries like this:

from x in repository.Clients.FilterByPropertyIfExists("Company", 5)
where x == ???
select x.Name;

[EDIT]

I've cleaned it up a bit and added a check on parameter visibility (must be a public, static property), as well as an ObjectQuery implementation (which will be automatically used for ObjectQuery and 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
    }
}

这篇关于如何包含一个检查Property的And()表达式及其值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆