How do I create a generic Expression that has an expression as a parameter

前端 未结 4 1909
死守一世寂寞
死守一世寂寞 2021-01-06 18:32

There is a DisplayNameFor(x=>x.Title) helper in ASP.Net MVC. I want to implement something similar in behavior.

I want to have a method that accepts

相关标签:
4条回答
  • 2021-01-06 18:53

    I believe this is what you're aiming for.

    public Func<User, bool> MyMethod<TProperty>(Expression<Func<User, TProperty>> func, ComparisonPredicate op, TProperty value)
    {
    
    
    }
    
    public enum ComparisonPredicate
    {
        Equal,
        Unequal,
        LessThan,
        LessThanOrEqualTo,
        GreaterThan,
        GreaterThanOrEqualTo
    }
    
    0 讨论(0)
  • 2021-01-06 19:06

    Does this satisfy your needs ?

    [TestClass]
    public class UnitTest1
    {
        public Expression<Predicate<T>> GetFilterPredicate<T, R>(Expression<Func<T, R>> selector, FilterOps operand, R value)
        {
            var parameter = selector.Parameters[0];
    
            var left = selector.Body;
            var right = Expression.Constant(value);
    
            var binaryExpression = Expression.MakeBinary(operand.ToExpressionType(), left, right);
            return Expression.Lambda<Predicate<T>>(binaryExpression, parameter);
        }
    
        [TestMethod]
        public void TestMethod1()
        {
            var p1 = this.GetFilterPredicate((User u) => u.Birthday.TimeOfDay.Hours, FilterOps.LessThan, 12);
            var p2 = this.GetFilterPredicate((User u) => u.Size, FilterOps.Equal, 180);
    
            var user = new User() { Birthday = new DateTime(2000, 1, 1), Size = 180 };
    
            Assert.IsTrue(p1.Compile()(user));
            Assert.IsTrue(p2.Compile()(user));
        }
    }
    
    public enum FilterOps
    {
        GreaterThan, LessThan, Equal
    }
    public static class MyExtensions
    {
        public static ExpressionType ToExpressionType(this FilterOps operand)
        {
            switch (operand)
            {
                case FilterOps.GreaterThan: return ExpressionType.GreaterThan;
                case FilterOps.LessThan: return ExpressionType.LessThan;
                case FilterOps.Equal: return ExpressionType.Equal;
                default: throw new NotSupportedException();
            }
        }
    }
    
    public class User { public DateTime Birthday { get; set; } public int Size { get; set; } }
    
    0 讨论(0)
  • 2021-01-06 19:12

    something like this:

    Expression<Func<TObject, TProperty>> GenerateAssignExpression<TObject, TProperty>
        (Expression<Func<TObject, TProperty>> getExpression,
        TProperty Value)
    {
        var getExpressionBody = getExpression.Body as MemberExpression;
        if (getExpressionBody == null)
        {
            throw new Exception("getExpressionBody is not MemberExpression: " + 
                    getExpression.Body);
        }
    
        var objectParameter = (ParameterExpression)getExpression.Parameters[0];
        ConstantExpression constant = Expression.Constant(Value, typeof(TProperty));
        var expAssign = Expression.Assign(e.Body, constant);
    
        return Expression.Lambda<Func<TObject, TProperty>>(expAssign, 
                objectParameter, 
                valueParameter);
    }
    
    0 讨论(0)
  • 2021-01-06 19:14

    The below method will produce a binary expression that will have a boolean return value

    Expression<Predicate<TObject>> 
         GenerateAssignExpression<TObject, TProperty>(
             Expression<Func<TObject, TProperty>> expression,
             ExpressionType op, 
             TProperty Value)
        {   
            return Expression.Lambda<Predicate<TObject>>(
                Expression.MakeBinary(op, expression, Expression.Constant(Value)),
                getExpression.Parameters[0]);
        }
    

    if you wish for a generic return type just change the Predicate<TObject> to Func<TObject,TReturn> (You need to replace both occurrences of `Predicate´

    0 讨论(0)
提交回复
热议问题