score:39
simplifying, here are several lines which you are trying to do (i use string instead product etc, but idea is the same):
expression<func<string, bool>> c1 = x => x.contains("111");
expression<func<string, bool>> c2 = y => y.contains("222");
var sum = expression.andalso(c1.body, c2.body);
var sumexpr = expression.lambda(sum, c1.parameters);
sumexpr.compile(); // exception here
please notice how i expanded your foreach into two expressions with x and y - this is exactly how it looks like for compiler, that are different parameters.
in other words, you are trying to do something like this:
x => x.contains("...") && y.contains("...");
and compiler wondering what is that 'y' variable??
to fix it, we need to use exactly the same parameter (not just name, but also reference) for all expressions. we can fix this simplified code like this:
expression<func<string, bool>> c1 = x => x.contains("111");
expression<func<string, bool>> c2 = y => y.contains("222");
var sum = expression.andalso(c1.body, expression.invoke(c2, c1.parameters[0])); // here is the magic
var sumexpr = expression.lambda(sum, c1.parameters);
sumexpr.compile(); //ok
so, fixing you original code would be like:
internal static class program
{
public class product
{
public string name;
}
private static void main(string[] args)
{
var searchstrings = new[] { "111", "222" };
var cachedproductlist = new list<product>
{
new product{name = "111 should not match"},
new product{name = "222 should not match"},
new product{name = "111 222 should match"},
};
var filterexpressions = new list<expression<func<product, bool>>>();
foreach (string searchstring in searchstrings)
{
expression<func<product, bool>> containsexpression = x => x.name.contains(searchstring); // not good
filterexpressions.add(containsexpression);
}
var filters = combinepredicates<product>(filterexpressions, expression.andalso);
var query = cachedproductlist.asqueryable().where(filters);
var list = query.take(10).tolist();
foreach (var product in list)
{
console.writeline(product.name);
}
}
public static expression<func<t, bool>> combinepredicates<t>(ilist<expression<func<t, bool>>> predicateexpressions, func<expression, expression, binaryexpression> logicalfunction)
{
expression<func<t, bool>> filter = null;
if (predicateexpressions.count > 0)
{
var firstpredicate = predicateexpressions[0];
expression body = firstpredicate.body;
for (int i = 1; i < predicateexpressions.count; i++)
{
body = logicalfunction(body, expression.invoke(predicateexpressions[i], firstpredicate.parameters));
}
filter = expression.lambda<func<t, bool>>(body, firstpredicate.parameters);
}
return filter;
}
}
but notice the output:
222 should not match
111 222 should match
not something you may expect.. this is result of using searchstring in foreach, which should be rewritten in the following way:
...
foreach (string searchstring in searchstrings)
{
var name = searchstring;
expression<func<product, bool>> containsexpression = x => x.name.contains(name);
filterexpressions.add(containsexpression);
}
...
and here is output:
111 222 should match
score:1
imho, no need to make the list:
var filterexpressions = new list<expression<func<product, bool>>>()
you may easily live with the following in visitor class:
public class filterconverter : ifilterconvertervisitor<filter> {
private lambdaexpression conditionclausepredicate { get; set; }
private parameterexpression parameter { get; set; }
public void visit(filter filter) {
if (filter == null) {
return;
}
if (this.parameter == null) {
this.parameter = expression.parameter(filter.basetype, "x");
}
conditionclausepredicate = and(filter);
}
public delegate getconditionclause() {
if (conditionclausepredicate != null) {
return conditionclausepredicate.compile();
}
return null;
}
private lambdaexpression and(filter filter) {
if (filter.basetype == null || string.isnullorwhitespace(filter.flattenpropertyname)) {
//something is wrong, passing by current filter
return conditionclausepredicate;
}
var conditiontype = filter.getcondition();
var propertyexpression = filter.basetype.getflattenpropertyexpression(filter.flattenpropertyname, this.parameter);
switch (conditiontype) {
case filtercondition.equal: {
var matchvalue = typedescriptor.getconverter(propertyexpression.returntype).convertfromstring(filter.match);
var propertyvalue = expression.constant(matchvalue, propertyexpression.returntype);
var equalexpression = expression.equal(propertyexpression.body, propertyvalue);
if (conditionclausepredicate == null) {
conditionclausepredicate = expression.lambda(equalexpression, this.parameter);
} else {
conditionclausepredicate = expression.lambda(expression.and(conditionclausepredicate.body, equalexpression), this.parameter);
}
break;
}
// and so on...
}
}
the code is not optimal, i know, i'm a beginner and a lot of everything to be implemented... but this stuff does work. the idea is to have the only parameterexpression per visitor class, then to construct expressions using this parameter. after, just concatenate all expressions per one lambdaexpression clause and compile to delegate, when needed.
Source: stackoverflow.com
Related Query
- LINQ error: variable 'x' of type 'y' referenced from scope '', but it is not defined
- Specification Pattern with Expressions causing error - variable 'x' of type '' referenced from scope '', but it is not defined
- EntityFrameworkCore Linq error: variable 'country.Country' of type 'Country' referenced from scope '', but it is not defined
- LINQ expressions. Variable 'p' of type referenced from scope, but it is not defined
- Variable 'x.Sub' of type 'SubType' referenced from scope '' but it is not defined error
- When mocking Workbook->Worksheets: variable 'p' of type 'Microsoft.Office.Interop.Excel.Workbook' referenced from scope '', but it is not defined
- Error with an EF query with nested predicates - variable of type X referenced from scope but it is not defined
- MemberExpression: InvalidOperationExpression variable 'x' referenced from scope '', but it is not defined
- InvalidOperationException: type 'System.String' referenced from scope '', but it is not defined
- Linq Expression referenced from scope but its not defined
- variable is referenced from scope, but not defined LINQ expression tree
- CRM 2011: An unhandled exception of type 'System.InvalidOperationException' occurred. referenced from scope '', but it is not defined
- Error when combining Lambda expressions: "variable 'foo' of type 'Foo' referenced from the scope '', but it is not defined
- Restrictions.On(_func) - Variable 'p' of type 'Product' referenced from scope'', but it is not defined on passthrough
- C# LINQ: 'variable 'x' of type referenced from scope '', but it is not defined'
- Expressions: Variable referenced from scope, but it is not defined exception
- Aggregate Linq Expressions: getting an exception of variable referenced from scope
- Ormlite + PredicateBuilder "variable referenced from scope '', but it is not defined"
- Enumerable.Empty<T>().AsQueryable(); This method supports the LINQ to Entities infrastructure and is not intended to be used directly from your code
- How to pass LinQ Expressions from F# to C# code
- Accessing transparent identifier in select throws it is not referenced from scope
- Query expressions over source type 'dynamic' or with a join sequence of type 'dynamic' are not allowed
- 'The LINQ expression node type 'Invoke' is not supported in LINQ to Entities' when lambda is passed as a parameter, but not when used directly
- LINQ: How to dynamically use an ORDER BY in linq but only if a variable is not string.empty or null
- creating Linq to sqlite dbml from DbLinq source code
- LIKE operator in FromSqlInterpolated/FromSqlRaw not working, but fluent API or LINQ expressions do
- Scope of Linq Expressions defined in a loop - At issue: closing over loop variable
- code first approach error: the specified type member 'yyyxx' is not supported in linq to entities
- An exception of type 'System.ArgumentException' occurred in EntityFramework.dll but was not handled in user code
- Create an xml node tree from a result set but combining repeated attributes using linq or expressions
More Query from same tag
- Dynamic Linq Sort not working for ArrayList
- Why is LINQ not letting me OrderBy one of my data points?
- LINQ Transform/Pivot
- Combine two items in a list
- Return all elements except for a specific element that also has no value
- PLINQ AsParallel error with datatable
- Linq: List of double values - differences between successor values
- How to do Linq LIKE or Contains when both values have strings added to them
- Insert a row of grid into datacontext
- Ordering Entity Framework items and child items for MVC view
- LINQ statement is not translatable
- Count Total issued per month using LINQ
- Sorting 2D data in a list
- Uniquifying a list (C#)
- Select specific time range on each day
- C# Checking if text-based answer is correct
- Counting occurrences of the first x elements of sublist in all sublists of the jagged list
- Make Reachable Class Out Of DataTable LINQToDataTable<T>()?
- what is the right syntax for OrderByDescending with condition?
- Linq - interrupt execution of stored procedure
- How to make a 'group by' on a Child's property and avoiding a 'NotSupportedException'
- Type Inference failed in a call to 'join' on nullable and non-nullable int
- Generic Sort by related object
- Linq2Xml - Getting parent items based on their children's attribute value
- LINQ to SQL Order of Evaluation of a Boolean
- AutoMapper ProjectTo fails with FirstOrDefault
- Simplify Lambda to Sum Sibling Tag Values using LINQ to XML
- Linq type conversion problem
- Sort even numbers from List using LINQ
- Display array after selecting with linq