MemberExpression to MemberExpression[] - linq

The objective is to get an array of MemberExpressions from two LambdaExpressions. The first is convertible to a MethodCallExpression that returns the instance of an object (Expression<Func<T>>). The second Lambda expression would take the result of the compiled first expression and return a nested member (Expression<Func<T,TMember>>). We can assume that the second Lambda expression will only make calls to nested properties, but may do several of these calls.
So, the signature of the method I am trying to create is :
MemberExpression[] GetMemberExpressionArray<T,TValue>(Expression<Func<T>> instanceExpression, Expression<Func<T,TValue>> nestedMemberExpression)
where nestedMemberExpression will be assumed to take an argument of the form
parent => parent.ChildProperty.GrandChildProperty
and the resulting array represents the MemberAccess from parent to ChildProperty and from the value of ChildProperty to GrandChildProperty.
I have already returned the last MemberExpression using the following extension method.
public static MemberExpression GetMemberExpression<T, TValue>(Expression<Func<T, TValue>> expression)
{
if (expression == null)
{
return null;
}
if (expression.Body is MemberExpression)
{
return (MemberExpression)expression.Body;
}
if (expression.Body is UnaryExpression)
{
var operand = ((UnaryExpression)expression.Body).Operand;
if (operand is MemberExpression)
{
return (MemberExpression)operand;
}
if (operand is MethodCallExpression)
{
return ((MethodCallExpression)operand).Object as MemberExpression;
}
}
return null;
}
Now, I know there are several ways to accomplish this. The most immediately intuitive to me would be to loop through the .Expression property to get the first expression and capture references to each MemberExpression along the way. This may be the best way to do it, but it may not. I am not extraordinarily familiar with the performance costs I get from using expressions like this. I know a MemberExpression has a MemberInfo and that reflection is supposed to hurt performance.
I've tried to search for information on expressions, but my resources have been very limited in what I've found.
I would appreciate any advice on how to accomplish this task (and this type of task, in general) with optimal performance and reliability.

I'm not sure why this has been tagged performance, but the easiest way I can think of to extract member-expressions from a tree is to subclass ExpressionVisitor. This should be much simpler than manually writing the logic to 'expand' different types of expressions and walk the tree.
You'll probably have to override the VisitMember method so that:
Each member-expression is captured.
Its children are visited.
I imagine that would look something like:
protected override Expression VisitMember(MemberExpression node)
{
_myListOfMemberExpressions.Add(node);
return base.VisitMember(node);
}
I'm slightly unclear about the remainder of your task; it appears like you want to rewrite parameter-expressions, in which case you might want to look at this answer from Marc Gravell.

Related

How can I intercept the result of an IQueryProvider query (other than single result)

I'm using Entity Framework and I have a custum IQueryProvider. I use the Execute method so that I can modify the result (a POCO) of a query after is has been executed. I want to do the same for collections. The problem is that the Execute method is only called for single result.
As described on MSDN :
The Execute method executes queries that return a single value
(instead of an enumerable sequence of values). Expression trees that
represent queries that return enumerable results are executed when
their associated IQueryable object is enumerated.
Is there another way to accomplish what I want that I missed?
I know I could write a specific method inside a repository or whatever but I want to apply this to all possible queries.
This is true that the actual signature is:
public object Execute(Expression expression)
public TResult Execute<TResult>(Expression expression)
However, that does not mean that the TResult will always be a single element! It is the type expected to be returned from the expression.
Also, note that there are no constraints over the TResult, not even 'class' or 'new()'.
The TResult is a MyObject when your expression is of singular result, like .FirstOrDefault(). However, the TResult can also be a double when you .Avg() over the query, and also it can be IEnumerable<MyObject> when your query is plain .Select.Where.
Proof(*) - I've just set a breakpoint inside my Execute() implementation, and I've inspected it with Watches:
typeof(TResult).FullName "System.Collections.Generic.IEnumerable`1[[xxxxxx,xxxxx]]"
expression.Type.FullName "System.Linq.IQueryable`1[[xxxxxx,xxxxx]]"
I admit that three overloads, one object, one TResult and one IEnumerable<TResult> would probably be more readable. I think they did not place three of them as extensibility point for future interfaces. I can imagine that in future they came up with something more robust than IEnumerable, and then they'd need to add another overload and so on. With simple this interface can process any type.
Oh, see, we now also have IQueryable in addition to IEnumerable, so it would need at least four overloads:)
The Proof is marked with (*) because I have had a small bug/feature in my IQueryProvider's code that has is obscuring the real behavior of LINQ.
LINQ indeed calls the generic Execute only for singular cases. This is a shortcut, an optimization.
For all other cases, it ... doesn't call Execute() it at all
For those all other cases, the LINQ calls .GetEnumerator on your custom IQueryable<> implementation, that what happens is dictated by .. simply what you wrote there. I mean, assuming that you actually provided custom implementations of IQueryable. That would be strange if you did not - that's just about 15 lines in total, nothing compared to the length of custom provider.
In the project where I got the "proof" from, my implementation looks like:
public System.Collections.IEnumerator GetEnumerator()
{
return Provider.Execute<IEnumerable>( this.Expression ).GetEnumerator();
}
public IEnumerator<TOut> GetEnumerator()
{
return Provider.Execute<IEnumerable<TOut>>( this.Expression ).GetEnumerator();
}
of course, one of them would be explicit due to name collision. Please note that to fetch the enumerator, I actually call the Execute with explicitely stated TResult. This is why in my "proof" those types occurred.
I think that you see the "TResult = Single Element" case, because you wrote i.e. something like this:
public IEnumerator<TOut> GetEnumerator()
{
return Provider.Execute<TOut>( this.Expression ).GetEnumerator();
}
Which really renders your Execute implementation without choice, and must return single element. IMHO, this is just a bug in your code. You could have done it like in my example above, or you could simply use the untyped Execute:
public System.Collections.IEnumerator GetEnumerator()
{
return ((IEnumerable)Provider.Execute( this.Expression )).GetEnumerator();
}
public IEnumerator<TOut> GetEnumerator()
{
return ((IEnumerable<TOut>)Provider.Execute( this.Expression )).GetEnumerator();
}
Of course, your implementation of Execute must make sure to return proper IEnumerables for such queries!
Expression trees that represent queries that return enumerable results are executed when their associated IQueryable object is enumerated.
I recommend enumerating your query:
foreach(T t in query)
{
CustomModification(t);
}
Your IQueryProvider must implement CreateQuery<T>. You get to choose the implemenation of the resulting IQueryable. If you want that IQueryable to do something to each row when enumerated, you get to write that implementation.
The final answer is that it's not possible.

How to replace lambda written in Where clause of Linq with equivalent delegate

I have an Query expression that uses a predicate type and lambda expression.
I am getting desired result with this. But I am not clear with how this expression is getting evaluated.
I tried to break this lambda expression by creating delegate and replacing condition under Where with delegate type.
If I have to rewrite the same thing with writing a delegate instead of anonymous type. What will be the syntax. How the delegate will be return for the same.
if (((DataTable)dgvAssignedRpm.DataSource).AsEnumerable()
.Where(row => row.Field<long>("FK_RPM_BTN_SETTING_ID") == objRpmButtonHolder.RpmSettingId).Count() > 1)
{
List<DataRow> listPkgBtnSettings = SearchForExistingSettingId();
}
void MethodSignature(...)
{
...
if (((DataTable)dgvAssignedRpm.DataSource).AsEnumerable()
.Where(RowCondition)
{
List<DataRow> listPkgBtnSettings = SearchForExistingSettingId();
}
...
}
// Where want a Func<T,bool> parameter
// T is the first parameter type (DataRow here)
// bool represents the return value
bool RowCondition(DataRow row)
{
return row.Field<long>("FK_RPM_BTN_SETTING_ID") == objRpmButtonHolder.RpmSettingId).Count() > 1
}
I assume the correct delegate replacement would be:
if (((DataTable)dgvAssignedRpm.DataSource).AsEnumerable().Where(
delegate(DataRow row) {
return (row.Field<long>("FK_RPM_BTN_SETTING_ID") == objRpmButtonHolder.RpmSettingId.Count() > 1);
}))
{
List<DataRow> listPkgBtnSettings = SearchForExistingSettingId();
}
But it's morning for me, so forgive me if I'm a bit off.
What the where desires is to give a DataRow as a parameter and a bool to return. You could just about fill in anything in the lambda or delegate, as long as it matches these requests.
To your question why it requests Func<> and how it works. The statement you're using is LINQ, so I found you a reference regarding this which can probably explain it better than me:
http://blogs.msdn.com/b/mirceat/archive/2008/03/13/linq-framework-design-guidelines.aspx
But yeah, the last type here in the Func<> is what it returns. (However, I can still recommend using the Lambda expression, as it's pretty clean, neat and serves the Func<> best.
(Also, look at what intellisence gives you when you write "new Func<....", it should give you a good idea of what Func wants and can do!)
Hope I was of help.

How to avoid Linq chaining to return null?

I have a problem with code contracts and linq. I managed to narrow the issue to the following code sample. And now I am stuck.
public void SomeMethod()
{
var list = new List<Question>();
if (list.Take(5) == null) { }
// resharper hints that condition can never be true
if (list.ForPerson(12) == null) { }
// resharper does not hint that condition can never be true
}
public static IQueryable<Question> ForPerson(this IQueryable<Question> source, int personId)
{
if(source == null) throw new ArgumentNullException();
return from q in source
where q.PersonId == personId
select q;
}
What is wrong with my linq chain? Why doesn't resharper 'complain' when analyzing the ForPerson call?
EDIT: return type for ForPerson method changed from string to IQueryable, which I meant. (my bad)
Reshaper is correct that the result of a Take or Skip is never null - if there are no items the result is an IEnumerable<Question> which has no elements. I think to do what you want you should check Any.
var query = list.Take(5);
if (!query.Any())
{
// Code here executes only if there were no items in the list.
}
But how does this warning work? Resharper cannot know that the method never returns null from only looking at the method definition, and I assume that it does not reverse engineer the method body to determine that it never returns null. I assume therefore that it has been specially hard-coded with a rule specifying that the .NET methods Skip and Take do not return null.
When you write your own custom methods Reflector can make assumptions about your method behaviour from the interface, but your interface allows it to return null. Therefore it issues no warnings. If it analyzed the method body then it could see that null is impossible and would be able to issue a warning. But analyzing code to determine its possible behaviour is an incredibly difficult task and I doubt that Red Gate are willing to spend the money on solving this problem when they could add more useful features elsewhere with a much lower development cost.
To determine whether a boolean expression can ever return true is called the Boolean satisfiability problem and is an NP-hard problem.
You want Resharper to determine whether general method bodies can ever return null. This is a generalization of the above mentioned NP-hard problem. It's unlikely any tool will ever be able to do this correctly in 100% of cases.
if(source == null) throw new ArgumentNullException();
That's not the code contract way, do you instead mean:
Contract.Require(source != null);

How do I combine LINQ expressions into one?

I've got a form with multiple fields on it (company name, postcode, etc.) which allows a user to search for companies in a database. If the user enters values in more than one field then I need to search on all of those fields. I am using LINQ to query the database.
So far I have managed to write a function which will look at their input and turn it into a List of expressions. I now want to turn that List into a single expression which I can then execute via the LINQ provider.
My initial attempt was as follows
private Expression<Func<Company, bool>> Combine(IList<Expression<Func<Company, bool>>> expressions)
{
if (expressions.Count == 0)
{
return null;
}
if (expressions.Count == 1)
{
return expressions[0];
}
Expression<Func<Company, bool>> combined = expressions[0];
expressions.Skip(1).ToList().ForEach(expr => combined = Expression.And(combined, expr));
return combined;
}
However this fails with an exception message along the lines of "The binary operator And is not defined for...". Does anyone have any ideas what I need to do to combine these expressions?
EDIT: Corrected the line where I had forgotten to assign the result of and'ing the expressions together to a variable. Thanks for pointing that out folks.
You can use Enumerable.Aggregate combined with Expression.AndAlso. Here's a generic version:
Expression<Func<T, bool>> AndAll<T>(
IEnumerable<Expression<Func<T, bool>>> expressions) {
if(expressions == null) {
throw new ArgumentNullException("expressions");
}
if(expressions.Count() == 0) {
return t => true;
}
Type delegateType = typeof(Func<,>)
.GetGenericTypeDefinition()
.MakeGenericType(new[] {
typeof(T),
typeof(bool)
}
);
var combined = expressions
.Cast<Expression>()
.Aggregate((e1, e2) => Expression.AndAlso(e1, e2));
return (Expression<Func<T,bool>>)Expression.Lambda(delegateType, combined);
}
Your current code is never assigning to combined:
expr => Expression.And(combined, expr);
returns a new Expression that is the result of bitwise anding combined and expr but it does not mutate combined.
EDIT: Jason's answer is now fuller than mine was in terms of the expression tree stuff, so I've removed that bit. However, I wanted to leave this:
I assume you're using these for a Where clause... why not just call Where with each expression in turn? That should have the same effect:
var query = ...;
foreach (var condition in conditions)
{
query = query.Where(condition);
}
Here we have a general question about combining Linq expressions. I have a general solution for this problem. I will provide an answer regarding the specific problem posted, although it's definitely not the way to go in such cases. But when simple solutions fail in your case, you may try to use this approach.
First you need a library consisting of 2 simple functions. They use System.Linq.Expressions.ExpressionVisitor to dynamically modify expressions. The key feature is unifying parameters inside the expression, so that 2 parameters with the same name were made identical (UnifyParametersByName). The remaining part is replacing a named parameter with given expression (ReplacePar). The library is available with MIT license on github: LinqExprHelper, but you may quickly write something on your own.
The library allows for quite simple syntax for combining complex expressions. You can mix inline lambda expressions, which are nice to read, together with dynamic expression creation and composition, which is very capable.
private static Expression<Func<Company, bool>> Combine(IList<Expression<Func<Company, bool>>> expressions)
{
if (expressions.Count == 0)
{
return null;
}
// Prepare a master expression, used to combine other
// expressions. It needs more input parameters, they will
// be reduced later.
// There is a small inconvenience here: you have to use
// the same name "c" for the parameter in your input
// expressions. But it may be all done in a smarter way.
Expression <Func<Company, bool, bool, bool>> combiningExpr =
(c, expr1, expr2) => expr1 && expr2;
LambdaExpression combined = expressions[0];
foreach (var expr in expressions.Skip(1))
{
// ReplacePar comes from the library, it's an extension
// requiring `using LinqExprHelper`.
combined = combiningExpr
.ReplacePar("expr1", combined.Body)
.ReplacePar("expr2", expr.Body);
}
return (Expression<Func<Company, bool>>)combined;
}
Assume you have two expression e1 and e2, you can try this:
var combineBody = Expression.AndAlso(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));
var finalExpression = Expression.Lambda<Func<TestClass, bool>>(combineBody, e1.Parameters).Compile();

How does LINQ implement the SingleOrDefault() method?

How is the method SingleOrDefault() evaluated in LINQ? Does it use a Binary Search behind the scenes?
Better than attempting to explain in words, I thought I'd just post the exact code of implementation in the .NET Framework, retrieved using the Reflector program (and reformatted ever so slightly).
public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
switch (list.Count)
{
case 0:
return default(TSource);
case 1:
return list[0];
}
}
else
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (!enumerator.MoveNext())
return default(TSource);
TSource current = enumerator.Current;
if (!enumerator.MoveNext())
return current;
}
}
throw Error.MoreThanOneElement();
}
It's quite interesting to oberserve that an optimisation is made if the object is of type IList<T>, which seems quite sensible. It simply falls back to enumerating over the object otherwise if the object implements nothing more specific than IEnumerable<T>, and does so just how you'd expect.
Note that it can't use a binary search because the object doesn't necessarily represent a sorted collection. (In fact, in almost all usage cases, it won't.)
I would assume that it simply performs the query and if the result count is zero, it returns the default instance of the class. If the result count is one, it returns that instance, and if the result count is greater than one, it throws an exception.
I don't think it does any searching, it's all about getting the first element of the source [list, result set, etc].
My best guess is that it just pulls the first element. If there is no first it returns the default (null, 0, false, etc). If there is a first, it attempts to pull the second result. If there is a second result it throws an exception. Otherwise it returns the first result.

Resources