I am following this question Returning a nested generic Expression<Func<T, bool>>
And I am interested in how compiler reads and compile it to
for example
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
PropertyInfo pi = typeof(T).GetProperty(prop);
MemberExpression me = Expression.MakeMemberAccess(pe, pi);
ConstantExpression ce = Expression.Constant(val);
BinaryExpression be = Expression.Equal(me, ce);
return Expression.Lambda<Func<T, bool>>(be, pe);
Update Also need explanation of each method
My question is what lamda expression should I expect after it compiles?
See the comments in the code below.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
var myType = new MyType();
myType.p = "Some Value";
var compareMethod = DoWork<MyType>("Some Value", "p");
var isEqual = compareMethod(myType);
}
public static Func<T, bool> DoWork<T>(object val, string prop)
{
//The code below will construct an expression like 'p => p.prop == value'
//Creates the parameter part of an expression. So the 'p =>' part of the expression.
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
//Get access to the property info, like the getter and setter.
PropertyInfo pi = typeof(T).GetProperty(prop);
// // Constructs the part of the expression where the member is referenced, so the 'p.prop' part.
MemberExpression me = Expression.MakeMemberAccess(pe, pi);
//Creates the constant part of the expression, the 'value' part.
ConstantExpression ce = Expression.Constant(val);
//creates the comparison part '==' of the expression.
//So this requires the left and right side of 'left == right'
//Which is the property and the constant value.
//So 'p.prop == value'
BinaryExpression be = Expression.Equal(me, ce);
//Puts the 'p => ' and 'p.prop == value' parts of the expression together to form the
//complete lambda
//Compile it to have an executable method according to the same signature, as
//specified with Func<T, bool>, so you put a class in of type T and
//the 'p.prop == value' is evaluated, and the result is returned.
return Expression.Lambda<Func<T, bool>>(be, pe).Compile();
}
}
public class MyType
{
public string p { get; set; }
}
}
That said, I think it is a complex way of only comparing. The usage case you have in mind may justify it. Are you working with LINQ-to-SQL or so that you have to work with expressions? In most cases from my epxerience, you can solve this with Funcs and interfaces, maybe in combination with a wrapper class in case of 3rd party classes. The code itself probably creates some in memory MSIL, which is then compiled in memory to native code using the Just-In-Time compiler of the CLR, where the allocation of the memory is marked as executable. I do not have detailed knowledge of how that works, this is just a guess. For more information on how memory allocation can be marked for different purposes see Memory Protection Constants.
Related
Trying to write a way to sort of dynamically look at data passed to me via json (I don't have it strictly typed). I have been mulling this over for days and I am 100% unsure of the syntax, but I get the concept.
Can anyone assist me write this so it works? The first 'if' needs to create a Linq "contains" with StringComparer.OrdinalIgnoreCase and the second if needs to create a Guid.Equals call.
I feel like a true idiot, but it has been close to 2 days and endless google searches. I even read the interface for the .Call commands and theres ~14 of them and I can't figure out which is for what. I haven't been able to get this to work even once.
public static IQueryable<T> FilterDynamic<T>(this IQueryable<T> query, string fieldName, object values)
{
ParameterExpression param = Expression.Parameter(typeof(T), "e");
MemberExpression prop = Expression.PropertyOrField(param, fieldName);
// We use nullable guids in <T>, so i have to convert to actual guid
UnaryExpression convertedExp = Expression.Convert(prop, prop.Type.GenericTypeArguments.Single());
MethodCallExpression body;
if (convertedExp.Type == typeof(string))
{
body = Expression.Call(typeof(Enumerable), "Contains", new[] {typeof(string)},
Expression.Constant(values), prop);
}
if (convertedExp.Type == typeof(Guid))
{
MethodInfo methd = convertedExp.Type.GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public, null,new Type[] { typeof(object) }, null);
body = Expression.Call(prop.Type, "Equals", new[] {typeof(string)}, Expression.Constant(values), prop);
}
// Other types need to just not do anything.
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(body, param);
return query.Where(predicate);
}
The error I get on line 35 is No generic method 'Equals' on type 'System.Guid' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.
EDIT:
I had to change my second if block like this:
body = Expression.Call(convertedExp, methd, Expression.Constant(values));
All my answers were found by reading this code https://github.com/dotnet/corefx/blob/master/src/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs
I would like to create the following expression dynamically:
e.Collection.Select(inner => inner.Property)
I created this code to do it, however I have an issue when I execute the expression call, someone knows what I'm doing wrong?
private static Expression InnerSelect<TInnerModel>(IQueryable source, ParameterExpression externalParameter, string complexProperty)
{
// Creates the expression to the external property. // this generates: "e.Collection".
var externalPropertyExpression = Expression.Property(externalParameter, complexProperty);
// Creates the expression to the internal property. // this generates: "inner => inner.Property"
var innerParameter = Expression.Parameter(typeof(TInnerModel), "inner");
var innerPropertyExpression = Expression.Property(innerParameter, "Property");
var innerLambda = Expression.Lambda(innerPropertyExpression, innerParameter);
return Expression.Call(typeof(Queryable), "Select", new [] { typeof(TInnerModel) }, externalPropertyExpression, innerLambda);
}
Error:
No generic method 'Select' on type 'System.Linq.Queryable' is
compatible with the supplied type arguments and arguments. No type
arguments should be provided if the method is non-generic.
So, first off, the primary problem is very simple. As the error message says, you haven't passed enough type arguments to Select. But when you fix that, you'll still have a problem, and that problem will be much harder for you to see and understand.
Let's dig into that.
You wish to represent this as an expression tree:
e.Collection.Select(inner => inner.Property)
Let's begin by rewriting it in its non-extension-method form.
Queryable.Select<A, B>(e.Collection, inner => inner.Property)
Where A is the collection member type and B is the type of Property.
Now, suppose you had this expression in your program. What would it actually do at runtime? It would construct an expression tree for the lambda and pass it to Queryable.Select. That is, it would do something like:
var innerParameter = parameterFactory(whatever);
var lambdaBody = bodyFactory(whatever);
var lambda = makeALambda(lambdaBody, innerParameter);
Queryable.Select<TInnerModel>(e.Collection, lambda);
Right? You with me so far?
Now, suppose we wish to translate this program fragment to an expression tree that could itself be the body of a lambda. That would be:
var theMethodInfoForSelect = whatever;
var receiverE = valueFactory(whatever);
var thePropertyInfoForCollection = whatever;
var theFirstArgument = propertyFactory(receiverE, thePropertyInfoForCollection);
...
Again, with me so far? Now, the crucial question: what is the second argument? It is NOT the value of lambda, which is what you are passing. Remember, what we are doing here is constructing an expression tree which represents the code that the compiler is generating for that thing, and the expression tree that is in lambda is not that. You're mixing levels!
Let me put it this way: the compiler is expecting "add one and three". You are passing 4. Those are very different things! One of them is a description of how to obtain a number and the other one is a number. You are passing an expression tree. What the compiler is expecting is a description of how to obtain an expression tree.
So: do you have to now write code that generates expression trees for all of lambda's construction code? Thank goodness no. We provided you a handy way to turn an expression tree into a description of how to produce an expression tree, which is the Quote operation. You need to use it.
So, what is the right sequence of events that you need to do to build your expression tree? Let's walk through it:
First, you'll need a ParameterExpression of the type of e, which you already have in hand. Let's suppose that is:
ParameterExpression eParam = Expression.Parameter(typeof(E), "e");
Next, you will need a method info for the Select method. Let's suppose you can correctly get that.
MethodInfo selectMethod = whatever;
That method takes two arguments, so let's make an array of argument expressions:
Expression[] arguments = new Expression[2];
You'll need a property info for your Collection property. I assume you can get that:
MethodInfo collectionGetter = whatever;
Now we can build the property expression:
arguments[0] = Expression.Property(eParam, collectionGetter);
Super. Next we need to start building that lambda. We need a parameter info for inner:
ParameterExpression innerParam = Expression.Parameter(typeof(Whatever), "inner");
We'll need a property info for Property, which I assume you can get:
MethodInfo propertyGetter = whatever;
Now we can build the body of the lambda:
MemberExpression body = Expression.Property(innerParam, propertyGetter);
The lambda takes an array of parameters:
ParameterExpression[] innerParams = { innerParam };
Build the lambda from the body and the parameters:
var lambda = Expression.Lambda<Func<X, int>>(body, innerParams);
Now the step you missed. The second argument is the quoted lambda, not the lambda:
arguments[1] = Expression.Quote(lambda);
Now we can build the call to Select:
MethodCallExpression callSelect = Expression.Call(null, selectMethod, arguments);
And we're done.
Give someone an expression tree and you give them an expression tree for a day; teach them how to find expression trees themselves and they can do it for a lifetime. How did I do that so fast?
Since I wrote the expression tree code generator, I had some immediate familiarity with the problem that you were likely to have. But that was ten years ago, and I did not do the above entirely from memory. What I did was I wrote this program:
using System;
using System.Linq.Expressions;
public interface IQ<T> {}
public class E
{
public IQ<X> C { get; set; }
}
public class X
{
public int P { get; set; }
}
public class Program
{
public static IQ<R> S<T, R>(IQ<T> q, Expression<Func<T, R>> f) { return null; }
public static void Main()
{
Expression<Func<E, IQ<int>>> f = e => S<X, int>(e.C, c => c.P);
}
}
Now I wished to know what code was generated by the compiler for the body of the outer lambda, so I went to https://sharplab.io/, pasted in the code, and then clicked on Results --> Decompile C#, which will compile the code to IL and then decompile it back to human-readable C#.
This is the best way I know of to quickly understand what the C# compiler is doing when it builds an expression tree, regardless of whether you know the compiler source code backwards and forwards. It's a very handy tool.
First of all I want to make you know that I've searched another questions and answers before making this one, but I cound't find any that would help me in this specific problem I am facing.
I need to filter registers based in two properties of its class, one of them being the field corresponding to the search, and the other one being a numeric code of another entity to which the register must be referenced in the database.
My search function has the following signature:
public List<TView> SearchByField(int parentCode, string fieldName, string filter);
I've tried to implement this using Expression Trees, and got it to get two expressions, but now I didn't get to combine these expressions to build one to pass to the final
Expression.AndAlso(parentCodeFilterExpression, textFilterExpression);
that will combine the too expressions in only one.
What I got so far was the code shown below (sorry for the long snippet, but I think this was necessary to make it easier to understand the question):
public List<TView> SearchPerField(int parentCode, string fieldName, string filter)
{
var lambdaExpression = GetLambdaExpressionForSearchByField(fieldName, filter, parentCode);
return new PersistenciaImpl<TView>().Where(lambdaExpression).ToList();
}
private Expression<Func<TView, bool>> GetLambdaExpressionForSearchByField(string fieldName, string filter, int parentCode)
{
Expression<Func<TView, bool>> textFilterExpression = GetTextFilterExpression(fieldName, filter);
Expression<Func<TView, bool>> parentCodeFilterExpression = GetParentCodeFilterExpression(parentCode);
Expression.Lambda<Func<TView, bool>>(textFilterExpression, parentCodeFilterExpression);
// THIS IS THE POINT. HOW TO MAKE THIS WORK?
Expression.AndAlso(parentCodeFilterExpression, textFilterExpression);
return textFilterExpression;
}
private Expression<Func<TView, bool>> GetParentCodeFilterExpression(int parentCode)
{
ParameterExpression parameter = Expression.Parameter(typeof(TView), "x");
Expression parent = Expression.Property(parameter, "Parent");
Expression parentCodeExpression = Expression.Property(parent, "Code");
Expression target = Expression.Constant(parentCode);
Expression containsMethod = Expression.Call(parentCodeExpression, "Equals", null, target);
Expression<Func<TView, bool>> textFilterExpression =
Expression.Lambda<Func<TView, bool>>(containsMethod, parameter);
return textFilterExpression;
}
private Expression<Func<TView, bool>> GetTextFilterExpression(string fieldName, string filter)
{
ParameterExpression parameter = Expression.Parameter(typeof(TView), "x");
Expression property = Expression.Property(parameter, fieldName);
Expression target = Expression.Constant(filter.ToUpper());
Expression containsMethod = Expression.Call(property, "Contains", null, target);
Expression<Func<TView, bool>> textFilterExpression =
Expression.Lambda<Func<TView, bool>>(containsMethod, parameter);
return textFilterExpression;
}
Thanks for any suggestion.
I've tried to implement this using Expression Trees, and got it to get two expressions, but now I didn't get to combine these expressions to build one to pass to the final
First, you need to declare a parameter for your final (outer) lambda. Then you need to invoke your two filter (inner) lambdas independently, passing in the same argument to each:
// using E = System.Linq.Expressions.Expression;
var item = E.Parameter(typeof(TView));
var combined = E.Lambda<Func<TView, bool>>(
E.AndAlso(
E.Invoke(parentCodeFilterExpression, item),
E.Invoke(textFilterExpression, item)),
item);
If you need these expressions to be compatible with a query provider like Entity Framework, things get a bit messier because Invoke expressions probably aren't supported. You'll have to manually inline the two filter lambdas, which requires walking each filter's body and replacing the inner parameter references with references to the outer lambda's parameter:
// using E = System.Linq.Expressions.Expression;
sealed class ParameterReplacementVisitor : ExpressionVisitor
{
private readonly IDictionary<E, E> _replacements;
public ParameterReplacementVisitor(IDictionary<E, E> replacements)
{
_replacements = replacements;
}
protected override Expression VisitParameter(ParameterExpression node)
{
E replacement;
if (_replacements.TryGetValue(node, out replacement))
return this.Visit(replacement);
return base.VisitParameter(node);
}
}
// ...
var item = E.Parameter(typeof(TView));
var visitor = new ParameterReplacementVisitor(
new Dictionary<E, E> {
{ parentCodeFilterExpression.Parameters[0], item },
{ textFilterExpression.Parameters[0], item }
}
);
var combined = E.Lambda<Func<TView, bool>>(
E.AndAlso(
visitor.Visit(parentCodeFilterExpression.Body),
visitor.Visit(textFilterExpression.Body)),
item);
Alternatively, if you are composing the inner expressions in a closed environment as your post suggests, you could simply pass the outer lambda parameter as an argument to the methods that construct the inner expressions, and return just the bodies (don't bother wrapping the inner filters in lambdas).
I think you need something like this:
MethodCallExpression where = Expression.Call((
typeof(Queryable),
"Where",
new Type[] { TView },
lambdaExpression );
Please note that I don't consider this a solution; it's merely an idea or example. Maybe this link will help you out.
You can compile an Expression<TDelegate> into a TDelegate by using the Compile method on the Expression:
Expression<Func<TView, bool>> lambdaExpression =
GetLambdaExpressionForSearchByField(fieldName, filter, parentCode);
Func<TView, bool> func = lambdaExpression.Compile();
Once you have that you can use it as a parameter for the Where function.
With the code above you can then use
return new PersistenciaImpl<TView>().Where(func).ToList();
I have the following extension method:
public static string ToPropertyName<T,E>(this Expression<Func<E, T>> propertyExpression)
{
if (propertyExpression == null)
return null;
string propName;
MemberExpression propRef = (propertyExpression.Body as MemberExpression);
UnaryExpression propVal = null;
// -- handle ref types
if (propRef != null)
propName = propRef.Member.Name;
else
{
// -- handle value types
propVal = propertyExpression.Body as UnaryExpression;
if (propVal == null)
throw new ArgumentException("The property parameter does not point to a property", "property");
propName = ((MemberExpression)propVal.Operand).Member.Name;
}
return propName;
}
I use linq expression when passing property names instead of strings to provide strong typing and I use this function to retrieving the name of the property as a string. Does this method use reflection?
My reason for asking is this method is used quite a lot in our code and I want it to be reasonably fast enough.
As far as I know, reflection is not involved in the sense that some kind of dynamic type introspection happens behind the scenes. However, types from the System.Reflection such as Type or PropertyInfo are used together with types from the System.Linq.Expressions namespace. They are used by the compiler only to describe any Func<T,E> passed to your method as an abstract syntax tree (AST). Since this transformation from a Func<T,E> to an expression tree is done by the compiler, and not at run-time, only the lambda's static aspects are described.
Remember though that building this expression tree (complex object graph) from a lambda at run-time might take somewhat longer than simply passing a property name string (single object), simply because more objects need to be instantiated (the number depends on the complexity of the lambda passed to your method), but again, no dynamic type inspection à la someObject.GetType() is involved.
Example:
This MSDN article shows that the following lambda expression:
Expression<Func<int, bool>> lambda1 = num => num < 5;
is transformed to something like this by the compiler:
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expression<Func<int, bool>> lambda1 =
Expression.Lambda<Func<int, bool>>(
numLessThanFive,
new ParameterExpression[] { numParam });
Beyond this, nothing else happens. So this is the object graph that might then be passed into your method.
Since you're method naming is ToPropertyName, I suppose you're trying to get the typed name of some particular property of a class. Did you benchmark the Expression<Func<E, T>> approach? The cost of creating the expression is quite larger and since your method is static, I see you're not caching the member expression as well. In other words even if the expression approach doesn't use reflection the cost can be high. See this question: How do you get a C# property name as a string with reflection? where you have another approach:
public static string GetName<T>(this T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
You can use it to get name of property or a variable, like this:
new { property }.GetName();
To speed up further, you would need to cache the member info. If what you have is absolutely Func<E, T> then your approach suits. Also see this: lambda expression based reflection vs normal reflection
A related question: Get all the property names and corresponding values into a dictionary
You can use Lambda Expression Objects to represent a lambda as an expression.
How do you create a Lambda Expression Object representing a generic method call, if you only know the type -that you use for the generic method signature- at runtime?
For example:
I want to create a Lambda Expression Objects to call:
public static TSource Last<TSource>( this IEnumerable<TSource> source )
But I only know what TSource is at runtime.
static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>()
{
var source = Expression.Parameter(
typeof(IEnumerable<T>), "source");
var call = Expression.Call(
typeof(Enumerable), "Last", new Type[] { typeof(T) }, source);
return Expression.Lambda<Func<IEnumerable<T>, T>>(call, source)
}
or
static LambdaExpression CreateLambda(Type type)
{
var source = Expression.Parameter(
typeof(IEnumerable<>).MakeGenericType(type), "source");
var call = Expression.Call(
typeof(Enumerable), "Last", new Type[] { type }, source);
return Expression.Lambda(call, source)
}
I don't fully understand the question, but the code that dtb wrote could be written simply as:
class MyUtils {
public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() {
return source => source.Last();
}
}
The code in the sample by dtb is pretty much the same thing as what the C# compiler automatically generates for you from this lambda expression (compiled as expression tree, because the return type is Expression).
If you know the type at runtime, then you can either use the solution by dtb or you can invoke the CreateLambda method (above) using Reflection, which may be slower, but allows you to write the code in the lambda in the natural C#:
var createMeth = typeof(MyUtils).GetMethod("CreateLambda");
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke();
The nice thing about this approach is that the code in CreateLambda can be much more complicated, which would be really hard to do using expression trees explicitly.