Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# String.Contains和String[]的表达式生成器函数_C#_.net_Expression Trees - Fatal编程技术网

C# String.Contains和String[]的表达式生成器函数

C# String.Contains和String[]的表达式生成器函数,c#,.net,expression-trees,C#,.net,Expression Trees,我很难创建一个表达式生成器函数来传递给NHibernate存储库的查询 基本上,我希望能够从各种对象属性(字符串)构建一个查询,并将它们的值与数组中的值进行比较。还可以添加其他查询语句 差不多 public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue> (Dictionary<Expression<Func<TElement, T

我很难创建一个表达式生成器函数来传递给NHibernate存储库的查询

基本上,我希望能够从各种对象属性(字符串)构建一个查询,并将它们的值与数组中的值进行比较。还可以添加其他查询语句

差不多

public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>
    (Dictionary<Expression<Func<TElement, TValue>>, IEnumerable<TValue>> expressionSet)
{
    List<Expression> newExpressions = new List<Expression>();

    foreach (var item in expressionSet)
    {
        if (null == item.Key) throw new ArgumentNullException("valueSelector");
        if (null == item.Value) throw new ArgumentNullException("values");

        ParameterExpression p = item.Key.Parameters.Single();

        if (!item.Value.Any()) return e => false;

        IEnumerable<Expression> expressions = item.Value
           .Select(value => (Expression)Expression.Equal(item.Key.Body, Expression.Constant(value, typeof(TValue))));
        Expression compExpression = expressions
            .Aggregate<Expression>((accumulate, equal) => Expression.OrElse(accumulate, equal));
        newExpressions.Add(Expression.Lambda<Func<TElement, bool>>(compExpression, p));
    }

    Expression accExpression = newExpressions
        .Aggregate<Expression>((accumulate, equal) => Expression.OrElse(accumulate, equal));

    return Expression.Lambda<Func<TElement, bool>>(accExpression);
}
公共静态表达式BuildOrExpression
(字典表达式集)
{
List newExpressions=newlist();
foreach(表达式集中的变量项)
{
如果(null==item.Key)抛出新的ArgumentNullException(“valueSelector”);
如果(null==item.Value)抛出新的ArgumentNullException(“值”);
ParameterExpression p=item.Key.Parameters.Single();
如果(!item.Value.Any())返回e=>false;
IEnumerable表达式=item.Value
.Select(value=>(Expression)Expression.Equal(item.Key.Body,Expression.Constant(value,typeof(TValue)));
表达式compExpression=表达式
.Aggregate((累计,相等)=>表达式.OrElse(累计,相等));
Add(Expression.Lambda(compExpression,p));
}
表达式accExpression=newExpressions
.Aggregate((累计,相等)=>表达式.OrElse(累计,相等));
返回表达式.Lambda(accExpression);
}
但不是执行
表达式.Equal
而是以某种方式执行
字符串.Contains


欢迎任何帮助。顺便说一下,上面的代码没有经过测试。

而不是
Expression。Equal
您需要使用
Expression。Call
和pass包含MethodInfo实例。像这样的

IEnumerable<Expression> expressions = item.Value.Select(value => 
   (Expression)Expression.Call(item.Key.Body, 
   typeof(String).GetMethod("Contains"), 
   Expression.Constant(value, typeof(TValue))));
IEnumerable expressions=item.Value.Select(Value=>
(表达式)表达式调用(item.Key.Body,
typeof(String).GetMethod(“包含”),
常量(值,类型(TValue));

我能够克服表达式组合问题,但我不确定这是最佳解决方案。我使用Vladimir和Joe Albahari(C#4书籍作者)提供的PredicateBuilder解决方案的任何人。这就是我想到的

    public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
    {
        if (null == valueSelector) throw new ArgumentNullException("valueSelector");
        if (null == values) throw new ArgumentNullException("values");

        ParameterExpression p = valueSelector.Parameters.Single();

        if (!values.Any()) return e => false;

        Expression<Func<string, string, bool>> expFunc = (name, value) => name.Contains(value);
        IEnumerable<Expression> equals = values.Select(value => (Expression)Expression.Call(valueSelector.Body, typeof(String).GetMethod("Contains"), Expression.Constant(value, typeof(TValue))));
        Expression body = equals.Aggregate<Expression>((accumulate, equal) => Expression.OrElse(accumulate, equal));

        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }
    public static Expression<Func<T, bool>> CombineOr<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
    }
    public static Expression<Func<T, bool>> CombineAnd<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
    }

    [TestMethod()]
    public void OfferComplexSearchTest()
    {
        using (var lifetime = container.BeginLifetimeScope())
        {
            IOfferRepository offerRepository = lifetime.Resolve<IOfferRepository>();
            List<Offer> offers = new List<Offer>();
            List<Expression<Func<Offer, bool>>> expressions = new List<Expression<Func<Offer, bool>>>();

            Expression<Func<Offer, bool>> finalExp = null;

            string[] orQuery = new string[2] { "director".ToUpper(), "jefe".ToUpper() };

            expressions.Add(LinqTools.BuildOrExpression<Offer, string>(c => c.Description.ToUpper(), orQuery));
            expressions.Add(LinqTools.BuildOrExpression<Offer, string>(c => c.Title.ToUpper(), orQuery));
            expressions.Add(LinqTools.BuildOrExpression<Offer, string>(c => c.Keywords.ToUpper(), orQuery));

            finalExp = expressions.Aggregate<Expression<Func<Offer, bool>>>((accomulate, equal) => LinqTools.CombineOr<Offer>(accomulate, equal));

            offers.AddRange(offerRepository.GetMany(LinqTools.CombineAnd<Offer>(finalExp, (x) => x.Publish)));

            Assert.IsTrue(offers.Count > 0, "Error: No Offers found.");
        }
    }
公共静态表达式BuildOrExpression(表达式值选择器,IEnumerable值)
{
如果(null==valueSelector)抛出新的ArgumentNullException(“valueSelector”);
如果(null==值)抛出新的ArgumentNullException(“值”);
ParameterExpression p=valueSelector.Parameters.Single();
如果(!values.Any())返回e=>false;
表达式expFunc=(名称,值)=>name.Contains(值);
IEnumerable equals=values.Select(value=>(Expression)Expression.Call(valueSelector.Body,typeof(String).GetMethod(“Contains”),Expression.Constant(value,typeof(TValue));
表达式体=等于.Aggregate((累计,等于)=>Expression.OrElse(累计,等于));
返回表达式.Lambda(body,p);
}
公共静态表达式组合(此表达式expr1,表达式expr2)
{
var invokedExpr=Expression.Invoke(expr2,expr1.Parameters.Cast());
返回Expression.Lambda(Expression.OrElse(expr1.Body,invokedExpr),expr1.Parameters);
}
公共静态表达式CombineAnd(此表达式expr1,表达式expr2)
{
var invokedExpr=Expression.Invoke(expr2,expr1.Parameters.Cast());
返回Expression.Lambda(Expression.AndAlso(expr1.Body,invokedExpr),expr1.Parameters);
}
[TestMethod()]
public void OfferComplexSearchTest()
{
使用(var lifety=container.BeginLifetimeScope())
{
IOFFERepository offerpository=生存期。解析();
列表提供=新列表();
列表表达式=新列表();
表达式finalExp=null;
字符串[]或查询=新字符串[2]{“director.ToUpper(),“jefe.ToUpper()};
Add(LinqTools.BuildOrExpression(c=>c.Description.ToUpper(),orQuery));
Add(LinqTools.BuildOrExpression(c=>c.Title.ToUpper(),orQuery));
Add(LinqTools.BuildOrExpression(c=>c.Keywords.ToUpper(),orQuery));
finalExp=表达式.Aggregate((acmulate,equal)=>LinqTools.CombineOr(acmulate,equal));
offers.AddRange(offerPresository.GetMany(LinqTools.CombineAnd(finalExp,(x)=>x.Publish));
Assert.IsTrue(offers.Count>0,“错误:未找到任何提供”);
}
}

Hello Vladimir,您的解决方案可能有效,但当我尝试使用它时,Aggregate()函数中出现异常。未为类型“System.Func
2[Job\u App.Model.Offer,System.Boolean]”和“System.Func
2[Job\u App.Model.Offer,System.Boolean]”定义二进制运算符或。有什么想法吗?