Is there way to convert Expression<Func<T, object>> to Expression<Func<object, object>> ?
I've had to do this before...
public static class ExpressionHelper {
public static Expression<Func<object,object>> ConvertParameterToObject<T>(this Expression<Func<T,object>> source){
return source.ReplaceParametersWithBase<T,object,object>();
}
public static Expression<Func<TBase,TResult>> ReplaceParameterWithBase<T,TResult,TBase>(this Expression<Func<T,TResult>> lambda)
where T :TBase
{
var param = lambda.Parameters.Single();
return (Expression<Func<TBase,TResult>>)
ParameterRebinder.ReplaceParameters(new Dictionary<ParameterExpression, ParameterExpression>
{
{ param, Expression.Parameter(typeof (TBase), param.Name) }
}, lambda.Body);
}
}
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
How about something like this:
static Expression<Func<object,object>> ConvertFunction<T>(Expression<Func<T,object>> function)
{
ParameterExpression p=Expression.Parameter(typeof(object));
return Expression.Lambda<Func<object,object>>
(
Expression.Invoke(function,Expression.Convert(p,typeof(T))), p
);
}
Then you can say something like this:
Expression<Func<string,object>> foo=s=>s.Length;
Expression<Func<object,object>> bar=ConvertFunction(foo);
var call=bar.Compile();
Console.Write(call("hello")) ; // Prints 5
Related
I have one expression that's defined like this:
Expression<Func<T1, T2, bool>> firstExpression;
and another one like this one:
Expression<Func<T1, bool>> secondExpression;
T2 is a value I know, T1 isn't. What I would like is to make the first expression into the second one, given the value of the parameter T2. If it would be regular Linq, it would be this:
var t2 = "Something I know";
secondExpression = t1 => fistExpression(t1, t2);
How would I do this using System.Linq.Expressions?
You can accomplish this with expression visitor:
public static class EmitUtils
{
private class ParameterReplacerVisitor : ExpressionVisitor
{
private ParameterExpression _source;
private Expression _target;
public ParameterReplacerVisitor(ParameterExpression source, Expression target)
{
_source = source;
_target = target;
}
public override Expression Visit(Expression node) =>
node == _source
? _target
: base.Visit(node);
}
public static Expression ReplaceParameter(Expression body, ParameterExpression srcParameter, Expression dstParameter) =>
new ParameterReplacerVisitor(srcParameter, dstParameter).Visit(body);
public static Expression<Func<T1, T3>> BuildClosure<T1, T2, T3>(Expression<Func<T1, T2, T3>> src, T2 closureValue)
{
var constExpression = Expression.Constant(closureValue, typeof(T2));
var body = ReplaceParameter(src.Body, src.Parameters[1], constExpression);
return Expression.Lambda<Func<T1, T3>>(body, src.Parameters[0]);
}
}
Here is sample usage:
[Test]
public void ClosureTest()
{
Expression<Func<int, string, bool>> CheckStringLength = (len, str) => str.Length < len;
var constString = "some string";
var result = EmitUtils.BuildClosure(CheckStringLength, constString);
Assert.That(result.Compile().Invoke(100), Is.True);
}
You can do it by swapping parameter expression with constant expression. Should looks like this
implement custom swap ExpressionVisitor
public class SwapVisitor : ExpressionVisitor
{
public Expression From { get; set; }
public Expression To { get; set; }
public override Expression Visit(Expression node)
{
return node == From ? To : base.Visit(node);
}
}
replace parameter T2 with constant
var swapper = new SwapVisitor
{
From = fistExpression.Parameters[1],
To = Expression.Constant(val)
};
var result = Expression.Lambda<Func<T, bool>>(
swapper.Visit(fistExpression.Body),
fistExpression.Parameters[0]);
Consider the following sample(firstLambda ans secondExpression needed just to see how compiler build the expression)
using System;
using System.Linq.Expressions;
static void Main(string[] args)
{
Expression<Func<string, int, bool>> firstExpression = (a, b) => a == b.ToString();
Func<string, int, bool> firstLambda = (a, b) => a == b.ToString();
Expression<Func<string, bool>> secondExpression = s => firstLambda(s, 45); // this expression I need just to see how it is compiled
var inputParameter = Expression.Parameter(typeof(string), "s");
var invocation = Expression.Invoke(firstExpression, inputParameter, Expression.Constant(47));
var ourBuildExpression = Expression.Lambda<Func<string, bool> > (invocation, new ParameterExpression[] { inputParameter }).Compile();
Console.WriteLine(ourBuildExpression("45"));
Console.WriteLine(ourBuildExpression("47"));
Console.ReadKey();
}
I checked in the debugger watch window the result of Expression<Func<string, bool>> secondExpression = s => firstLambda(s, 45); it was Invoke expression, so I constructed the same manually.
And you can see the test calls return and print False and True as expected.
I have following interface:
public interface IHasSchoolId
{
long? SchoolId { get; set; }
}
and following entity:
public class Student : IHasSchoolId
{
long? SchoolId { get; set; }
}
then there is following entity manager implementing empty interface IEntityManager<T>:
public class HasSchoolIdManager: IEntityManager<IHasSchoolId>
{
public static Expression<Func<IHasSchoolId, bool>> Filter()
{
return x=> x.SchoolId != null; //this is just an example
}
}
and finally I have following method:
private Expression<Func<TEntity, bool>> GetFilters<TEntity>()
{
Expression<Func<TEntity, bool>> result = null;
var entityManagers = //geting entitymanagers that are assinable to TEntity, like the one above and a lot more like IEntityManager<Student> itself
foreach (var entityManager in entityManagers)
{
var filterMethod = entityManager.GetMethod("Filter");
if (filterMethod != null)
result = AndAlso(result, (Expression<Func<TEntity, bool>>) filterMethod.Invoke(null, null)); //this line throws exception
}
return result;
}
and then when I'm calling the method like GetFilters<Student>() im getting following exception:
System.InvalidCastException: 'Unable to cast object of type 'System.Linq.Expressions.Expression[System.Func[WebCore.Models.Infrastructure.Interfaces.IHasSchoolId,System.Boolean]]' to type 'System.Linq.Expressions.Expression[System.Func[WebCore.Models.Student,System.Boolean]]'.'
by the way, this is my AndAlso method which works fine:
private Expression<Func<T, bool>> AndAlso<T>(
Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
if (expr1 == null)
return expr2;
if (expr2 == null)
return expr1;
ParameterExpression param = expr1.Parameters[0];
if (ReferenceEquals(param, expr2.Parameters[0]))
{
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(expr1.Body, expr2.Body), param);
}
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(
expr1.Body,
Expression.Invoke(expr2, param)), param);
}
and here is my empty IEntityManager interface:
public interface IEntityManager<T>
{
}
Note: not all my entities implements IHasSchoolId interface, there are many other interfaces, this is just an example
i think my question is, how to cast from Expression<Func</*an interface*/, bool>> to Expression<Func</*a class that implements that interface*/, bool>>
using reflection because as you can see, im calling the filter method using reflection
here is what i finally did:
Expression<Func<T, bool>> expression = null;
var managers = GetEntityManagers<T>();
foreach (var manager in managers)
{
var expr2 = manager.GetMethod("Filter")?.Invoke(null, null) as dynamic;
if (expr2 == null) continue;
var transformedExpr = Transform<T>(expr2) as Expression<Func<T, bool>>;
expression = expression == null ? transformedExpr : expression.AndAlso(transformedExpr);
}
and here is the transform function:
private class Visitor : ExpressionVisitor
{
private Expression _parameter;
public Visitor(Expression parameter)
{
_parameter = parameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return _parameter;
}
}
private static Expression<Func<T, bool>> Transform<T>(dynamic expression)
{
ParameterExpression parameter = Expression.Parameter(typeof(T));
Expression body = new Visitor(parameter).Visit(expression.Body);
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
Is it possible to convert a member epxression together with an object to a method binary expression in c#?
What i've tried so far:
public static void SaveBy<T>(this IDbConnection db, T obj, Expression<Func<T, object>> exp) where T : new()
{
var com = exp.Compile();
if (db.Update(obj, e => exp == com.Invoke(obj)) <= 0)
{
db.Insert(obj);
}
}
public static void UpdateBy<T>(this IDbConnection db, T obj, Expression<Func<T, bool>> exp) where T : new()
{
db.Update(obj, exp);
}
what i am trying to achieve is make a method that can be called with
x.SaveBy(object,model=>model.property)
which will call x.Update, converting a MemberExpression into a methodBinaryExpression like this:
x.Update(object, model=>model.property == object.property);
Half way solution
public static void SaveBy<T>(this IDbConnection db, T obj, Expression<Func<T, object>> exp) where T : new()
{
var result = exp.Compile().Invoke(obj);
var exp2 = Expression.Lambda<Func<T, bool>>(Expression.Equal(exp.Body, Expression.Constant(result)), exp.Parameters);
if (db.Update(obj, exp2) <= 0)
{
db.Insert(obj);
}
}
You can create just new expression
model=>model.property == object.property
public static void SaveBy<T, TProp>(this IDbConnection db, T obj, Expression<Func<T, TProp>> exp) where T : new()
{
var memberExp = (MemberExpression)exp.Body;
var objPropExp = Expression.PropertyOrField(Expression.Constant(obj), memberExp.Member.Name);
var equalExp = Expression.Equal(exp.Body, objPropExp);
var exp2 = Expression.Lambda<Func<T, bool>>(equalExp, exp.Parameters);
//exp2 = {model => (model.prop == value(object).prop)}
if (db.Update(obj, exp2) <= 0)
{
db.Insert(obj);
}
}
I have a situation where I need to translate the local variables reference in a linq query to its values.
For this I'm using this class to do a translate local variable reference in a query :
public static class Evaluator
{
public static Expression PartialEval(Expression expression, Func<Expression, bool> fnCanBeEvaluated)
{
return new SubtreeEvaluator(new Nominator(fnCanBeEvaluated).Nominate(expression)).Eval(expression);
}
public static Expression PartialEval(Expression expression)
{
return PartialEval(expression, Evaluator.CanBeEvaluatedLocally);
}
private static bool CanBeEvaluatedLocally(Expression expression)
{
return expression.NodeType != ExpressionType.Parameter;
}
class SubtreeEvaluator: ExpressionVisitor
{
HashSet<Expression> candidates;
internal SubtreeEvaluator(HashSet<Expression> candidates)
{
this.candidates = candidates;
}
internal Expression Eval(Expression exp)
{
return this.Visit(exp);
}
protected override Expression Visit(Expression exp)
{
if (exp == null)
{
return null;
}
if (this.candidates.Contains(exp))
{
return this.Evaluate(exp);
}
return base.Visit(exp);
}
private Expression Evaluate(Expression e)
{
if (e.NodeType == ExpressionType.Constant)
{
return e;
}
LambdaExpression lambda = Expression.Lambda(e);
Delegate fn = lambda.Compile();
return Expression.Constant(fn.DynamicInvoke(null), e.Type);
}
}
class Nominator : ExpressionVisitor
{
Func<Expression, bool> fnCanBeEvaluated;
HashSet<Expression> candidates;
bool cannotBeEvaluated;
internal Nominator(Func<Expression, bool> fnCanBeEvaluated)
{
this.fnCanBeEvaluated = fnCanBeEvaluated;
}
internal HashSet<Expression> Nominate(Expression expression)
{
this.candidates = new HashSet<Expression>();
this.Visit(expression);
return this.candidates;
}
protected override Expression Visit(Expression expression)
{
if (expression != null)
{
bool saveCannotBeEvaluated = this.cannotBeEvaluated;
this.cannotBeEvaluated = false;
base.Visit(expression);
if (!this.cannotBeEvaluated)
{
if (this.fnCanBeEvaluated(expression))
{
this.candidates.Add(expression);
}
else
{
this.cannotBeEvaluated = true;
}
}
this.cannotBeEvaluated |= saveCannotBeEvaluated;
}
return expression;
}
}
}
And after to translate local variable reference , is used like this :
public class DbQueryProvider : QueryProvider
{
// …
private string Translate(Expression expression)
{
expression = Evaluator.PartialEval(expression);
return new QueryTranslator().Translate(expression);
}
}
For example if I have this expression :
string ct = "London";
var query = db.Customers.Where(c => c.City == ct);
the returned expression after translation will be :
SELECT * FROM (SELECT * FROM Customers) AS T WHERE (City = 'London')
The code is working ok , with all the types of variables , except of DateTime.
In my database I save only the Date part ( without time ) , for example 02/03/2012.
Now if I have this query :
DateTime dt1 = Convert.ToDateTime("01/01/2012");
var query = db.Orders.Where(c => c.dt == dt1);
If I try to translate , the returned expression is :
SELECT * FROM (SELECT * FROM Orders) AS T WHERE (dt = '01/01/2012 12:00:00 AM')
As you can see the translated query contains the time at the end , and my query everytime return no records.
What can I do ?
var query = db.Orders.Where(c => c.dt == dt1.ToString("MM/dd/yyyy"));
Looking for a clean way to discover the string name of a method in a type safe way.
Here is what I have for properties, but I'm having trouble figuring out how to do it for methods.
class Program
{
class Customer
{
public String Id { get; set; }
}
public static String GetPropertyName<T>(
Expression<Func<T, Object>> selector) where T : class
{
var expression = (MemberExpression)selector.Body;
return expression.Member.Name;
}
static void Main(string[] args)
{
String propertyName = GetPropertyName<Customer>(c => c.Id);
}
}
Pretty much by changing to:
var expression = (MethodCallExpression)selector.Body;
return expression.Method.Name;
with the notable exception that you will need an Action<T> option to handle void methods. You will have to supply dummy parameter values, of course - if you really want you can obtain those too.
Actually, your existing code might not be robust; you may need to throw away a cast operation (to box the int to an object).
public static string GetMethodName<T>(Expression<Func<T, Object>> selector) where T : class
{
var expression = (MethodCallExpression)(selector.Body is UnaryExpression ? ((UnaryExpression)selector.Body).Operand : selector.Body);
return expression.Method.Name;
}
public static string GetMethodName<T>(Expression<Action<T>> selector) where T : class
{
var expression = (MethodCallExpression)(selector.Body is UnaryExpression ? ((UnaryExpression)selector.Body).Operand : selector.Body);
return expression.Method.Name;
}
If it helps, our code base uses the following:
public class TypeHelper
{
private static PropertyInfo GetPropertyInternal(LambdaExpression p)
{
MemberExpression memberExpression;
if (p.Body is UnaryExpression)
{
UnaryExpression ue = (UnaryExpression)p.Body;
memberExpression = (MemberExpression)ue.Operand;
}
else
{
memberExpression = (MemberExpression)p.Body;
}
return (PropertyInfo)(memberExpression).Member;
}
public static string GetPropertyName<TObject>(Expression<Func<TObject, object>> p)
{
return GetPropertyNameInternal(p);
}
public static string GetPropertyName<TObject, T>(Expression<Func<TObject, T>> p)
{
return GetPropertyNameInternal(p);
}
public static string GetPropertyName<T>(Expression<Func<T>> p)
{
return GetPropertyNameInternal(p);
}
public static string GetPropertyName(Expression p)
{
return GetPropertyNameInternal((LambdaExpression) p);
}
private static string GetPropertyNameInternal(LambdaExpression p)
{
return GetPropertyInternal(p).Name;
}
public static PropertyInfo GetProperty<TObject>(Expression<Func<TObject, object>> p)
{
return GetPropertyInternal(p);
}
public static PropertyInfo GetProperty<TObject, T>(Expression<Func<TObject, T>> p)
{
return GetPropertyInternal(p);
}
public static PropertyInfo GetProperty<T>(Expression<Func<T>> p)
{
return GetPropertyInternal(p);
}
}
That gives you the ability to do:
var propertyName = TypeHelper.GetPropertyName<Customer>(c => c.Id);
Or
var propertyName = TypeHelper.GetPropertyName(() => this.Id); // If inside Customer class
If you happen to have System.Web.Mvc, you can use ExpressionHelper.GetExpressionText(expression), like so:
Expression<Func<Response, string>> expression = r => r.Message;
Assert.AreEqual("Message", ExpressionHelper.GetExpressionText(expression));
(Response being a custom class with a Message property.)