score:2
It's failing because SelectMany<TSource, TResult>
method expects
Expression<Func<TSource, IEnumerable<TResult>>>
while you are passing
Expression<Func<TSource, ICollection<TResult>>>
These are not the same and the later is not convertible to the former simply because Expression<TDelegate>
is a class, and classes are invariant.
Taking your code, the expected lambda result type is like this:
var par = Expression.Parameter(origType, "x");
var propExpr = Expression.Property(par, property);
var firstGenType = reflectedType.GetGenericArguments()[0];
var resultType = typeof(IEnumerable<>).MakeGenericType(firstGenType);
Now you can either use Expression.Convert
to change (cast) the property type:
var lambda = Expression.Lambda(Expression.Convert(propExpr, resultType), par);
or (my preferred) use another Expression.Lambda
method overload with explicit delegate type (obtained via Expression.GetFuncType
):
var lambda = Expression.Lambda(Expression.GetFuncType(par.Type, resultType), propExpr, par);
Either of these will solve your original issue.
Now before you get the next exception, the following line:
var genericToListMethod = enumerableToListMethod.MakeGenericMethod(new[] { actualType });
is also incorrect (because when you pass "Work.Locations", the actualType
will be ICollection<Location>
, not Location
which ToList
expects), so it has to be changed to:
var genericToListMethod = enumerableToListMethod.MakeGenericMethod(new[] { actual.ElementType });
In general you could remove actualType
variable and always use IQueryable.ElementType
for that purpose.
Finally as a bonus, there is no need to find manually the generic method definitions. Expression.Call
has a special overload which allows you to easily "call" static generic (and not only) methods by name. For instance, the SelectMany
"call" would be like this:
selectExpression = Expression.Call(
typeof(Queryable), nameof(Queryable.SelectMany), new [] { origType, firstGenType },
queryable.Expression, lambda);
and calling Select
is similar.
Also there is no need to create additional lambda expression, compile and dynamically invoke it in order to get the resulting IQueryable
. The same can be achieved by using IQueryProvider.CreateQuery
method:
//var result = Expression.Lambda(selectExpression).Compile().DynamicInvoke() as IQueryable;
var result = queryable.Provider.CreateQuery(selectExpression);
score:0
You use your method with a type of ICollection<T>
, but your expression takes a IEnumerable<T>
as input. And SelectMany()
takes a IQueryable<T>
as input. Both IQueryable<T>
and ICollection<T>
are derived from IEnumerable<T>
, but if you need a IQueryable<T>
you cant give a ICollection<T>
.
This would be the same as the following example:
class MyIEnumerable
{ }
class MyICollection : MyIEnumerable
{ }
class MyIQueryable : MyIEnumerable
{ }
private void MethodWithMyIQueryable(MyIQueryable someObj)
{ }
private void DoSth()
{
//valid
MethodWithMyIQueryable(new MyIQueryable());
//invalid
MethodWithMyIQueryable(new MyICollection());
}
They share the same inheritance from object, but still have no linear inheritance to each other.
Try casting/converting your ICollection<T>
to IEnumerable<T>
and then give that as parameter.
Source: stackoverflow.com
Related Query
- Call SelectMany with Expression.Call - wrong argument
- How do I build Expression Call for Any Method with generic parameter
- Expression Tree with Property Inheritance causes an argument exception
- return dynamic object with all child nodes as Json in - error: cannot use a lambda expression as an argument to a dynamically dispatched
- C# Generic static call with Expression fails
- ForEach loop with Lambda expression in Razor code MVC 5 For List<T>
- How to add SelectMany to an Expression Tree with Expression.Call
- How to call Expression Func with two input parameters
- Lambda expression with statement body error in previously working code
- What's wrong with my translation from Linq Query Expression to Method-Based Query?
- Some confusion with conversion of FROM clauses into a call to SelectMany
- Expression Call with Type Combining lambda linq where
- Saved projection expression for re-use in different linq expressions with two source objects
- Call Expression within a LINQ to Entities with LINQkit
- How to call an Sql User defined Function using Entity frame work Code first approach with LInq c#
- I am having trouble with the code below. It is saying 'results' is an expression type '?'. which is not a collection type
- "A lambda expression with a statement body cannot be converted to an expression tree"
- How to flatten nested objects with linq expression
- Calling generic method with a type argument known only at execution time
- Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type
- Error: "The specified LINQ expression contains references to queries that are associated with different contexts"
- What does this C# code with an "arrow" mean and how is it called?
- How does LINQ expression syntax work with Include() for eager loading
- Working with nullable types in Expression Trees
- Can I use Linq's Except() with a lambda expression comparer?
- LINQ ToListAsync expression with a DbSet
- How Build Lambda Expression Tree with multiple conditions
- lambda expression join multiple tables with select and where clause
- What does "Replace with single call to single" mean?
- Selecting multiple columns with linq query and lambda expression
More Query from same tag
- Order by fileinfo extension and name
- Can I generate an async method dynamically using System.Linq.Expressions?
- Change binding at runtime to a particular element of a list based off property of the list item
- LINQ Group By and merge sublist of Group back into unique list
- Why is a my List.Intersect returning different results than a Where(List.Contains)?
- How I can compare the LINQ result?
- Query multiple tables with LINQ, grab results to dictionary
- Performance of Linq on entity framework vs SQL stored procedure
- Accessing XElement with specific value
- Linq to Sharepoint results in invalid cast
- Entity framework select all related items in fact table with condition in dimension table
- Why does Linq do joins differently
- Dynamic LINQ - Is There A .NET 4 Version?
- Good Way To Handle XML Change
- LINQ query not returning expected results
- InvalidTaskException when trying to get list of entities from a database
- Linq issue select Sum of one column minus another from different table
- Add Try-Catch Block to XAML Code
- Why are the properties of my partial class empty after I've run my LINQ query?
- Find a combination of two elements that have not been viewed together (LINQ, SQL or C#)
- Selecting an enemy from a non sorted weighted list
- Most efficient algorithm for merging sorted IEnumerable<T>
- C# IEnumerable being reset in child method
- Combining Tables With Different Data Using Linq in MVC?
- Convert if-else within a foreach loop to LINQ
- Getting Function Evaluation Timedout error when using function inside linq query
- Retrieve Umbraco Tags datatype field in a LINQ query
- Clueless about removing a duplicate reference
- "Left XOR" between two lists with LINQ
- Linq To Sql - Update a value when another value changes