Create Expression from Func

Create Expression from Func

You can not recreate an expression based on a method since an expression needs to know the original statements, not IL. You can however create an Expresson which makes a method call to your func like:

Func<int> func = () => 1;
Expression<Func<int>> expression = Expression.Lambda<Func<int>>(Expression.Call(func.Method));

Note however that systems like EF can't really work with this

How to create ExpressionFuncTModel, string expression from Property Name

It looks like you want to call ModelMetadata.FromLambdaExpression, not FromStringExpression. You can create an expression like

x => x.PropertyName

from scratch, like this:

// Get a reference to the property
var propertyInfo = ExpressionHelper.GetPropertyInfo<TModel>(propertyName);
var model = ExpressionHelper.Parameter<TModel>();

// Build the LINQ expression tree backwards:
// x.Prop
var key = ExpressionHelper.GetPropertyExpression(model, propertyInfo);
// x => x.Prop
var keySelector = ExpressionHelper.GetLambda(typeof(TModel), propertyInfo.PropertyType, model, key);

To make the code more readable, the nitty-gritty expression tree manipulation is moved into this helper class:

public static class ExpressionHelper
{
private static readonly MethodInfo LambdaMethod = typeof(Expression)
.GetMethods()
.First(x => x.Name == "Lambda" && x.ContainsGenericParameters && x.GetParameters().Length == 2);

private static MethodInfo GetLambdaFuncBuilder(Type source, Type dest)
{
var predicateType = typeof(Func<,>).MakeGenericType(source, dest);
return LambdaMethod.MakeGenericMethod(predicateType);
}

public static PropertyInfo GetPropertyInfo<T>(string name)
=> typeof(T).GetProperties()
.Single(p => p.Name == name);

public static ParameterExpression Parameter<T>()
=> Expression.Parameter(typeof(T));

public static MemberExpression GetPropertyExpression(ParameterExpression obj, PropertyInfo property)
=> Expression.Property(obj, property);

public static LambdaExpression GetLambda<TSource, TDest>(ParameterExpression obj, Expression arg)
=> GetLambda(typeof(TSource), typeof(TDest), obj, arg);

public static LambdaExpression GetLambda(Type source, Type dest, ParameterExpression obj, Expression arg)
{
var lambdaBuilder = GetLambdaFuncBuilder(source, dest);
return (LambdaExpression)lambdaBuilder.Invoke(null, new object[] { arg, new[] { obj } });
}
}

Building the expression tree from scratch gives you the most flexibility in creating the lambda expression. Depending on the target property type, it may not always be an Expression<Func<TModel, string>> - the last type could be an int or something else. This code will build the proper expression tree no matter the target property type.

How to create ExpressionFuncobject from property name

OK, I hope, i have finally understood, what do you need :)

I suggest to create such extension method:

public static class EntityExtensions
{
public static Expression<Func<object>> ToExpression(this Entity entity, string property)
{
var constant = Expression.Constant(entity);
var memberExpression = Expression.Property(constant, property);
Expression convertExpr = Expression.Convert(memberExpression, typeof(object));
var expression = Expression.Lambda(convertExpr);

return (Expression<Func<object>>)expression;
}
}

and than call it this way:

var entity = new Entity { Id = 4711 };
var expression = entity.ToExpression("Id");
var result = expression.Compile().DynamicInvoke();

You have to give entity as a parameter.

People, who downvote accepted answer, could explain, what the probem it.

How Do I Create an ExpressionFunc with Type Parameters from a Type Variable

You need to create the appropriate delegate type, then pass that to the Expression.Lambda method. For example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

class Test
{
static void Main()
{
var type = typeof(string);
var body = Expression.Constant(true);
var parameter = Expression.Parameter(type);
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
dynamic lambda = Expression.Lambda(delegateType, body, parameter);
Console.WriteLine(lambda.GetType()); // Expression<string, bool>
}
}

Now of course your body would normally not just be a constant - but we don't know what you need to do there. From your edited question, it looks like you do have some statically typed knowledge of the type, otherwise you wouldn't be able to express that lambda expression. So either you need to build up the expression tree manually to be the equivalent of the lambda expression (using Expression.Property etc) or create one expression tree from what you know, and then use an expression tree visitor to adapt that to the actual type.

EDIT: Note that the type of lambda must be dynamic for it to work as the second argument to Queryable.Where, otherwise the execution-time version of the C# compiler will use the static type of the variable (which would just be LambdaExpression) to constrain overload resolution. You want it to match the actual Expression<TDelegate> type, which you can't express at compile-time, so you need to use dynamic.

How to create ExpressionFuncTModel, TProperty without TProperty type explicit

You can in fact do this, but the type becomes unknown. The object returned from this method will be of the proper type Expression<Func<Test, string>> but cannot be strong typed at compile time:

    static LambdaExpression CreateExpression<TModel>(string propertyName)
{
var t = typeof(TModel);
var param = Expression.Parameter(typeof(TModel), "x");
//get the type for the 2nd generic arg
var propType = t.GetProperty(propertyName).PropertyType;
//make the generic type Func<TModel, TProp>
Type genericFuncType = typeof(Func<,>).MakeGenericType(new Type[] { typeof(TModel), propType });
//get the Expression.Lambda method
MethodInfo mi = typeof(Expression).GetMethods().First(a => a.Name == "Lambda" && a.GetParameters().Length == 2);
//get the Expression.Lambda<Func<TModel, TProp>> method
MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { genericFuncType });
//Call Expression.Lambda<Func<TModel, TProp>>
return (LambdaExpression)mi2.Invoke(null, new object[] { Expression.PropertyOrField(param, propertyName), new ParameterExpression[] { param }});
}

However note that the return type is now somewhat unknown and will need cast to use (or use dynamic).

So now you need even more code to cast it. Perhaps this would be useful in some sort of factory or such - not sure your use case.

class Program
{
public static void Main(string[] args)
{
var theExpression = CreateExpression<Test>("Name");
var theExpressionStrongType = theExpression as Expression<Func<Test, string>>;
//now you could use theExpressionStrongType

//or do this and go wild. :)
dynamic d = theExpression;

Console.ReadKey();
}
}
class Test
{
public string Name { get; set; }
}

Disclaimer: if you seriously want to use this in a production environment, I would clean up the code a LOT to just get refection types once, etc, etc...

Create an empty Expression Func

You can use a Func returning true:

Expression<Func<Activity, bool>> filter = u => true;

But I would say that possibly better approach is to pass null value for filter and check it inside GetPaginatedAsync like that:

IQueryable<TEntity> query = _context.Set<TEntity>();
if(filter != null)
{
query = query.Where(filter);
}

await query.ToListAsync();

converting a .net FuncT to a .net ExpressionFuncT

Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).

Related fact

This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.



Related Topics



Leave a reply



Submit