C# How to convert an Expression> to an Expression>

后端 未结 4 1686
轮回少年
轮回少年 2020-12-14 10:46

I have used C# expressions before based on lamdas, but I have no experience composing them by hand. Given an Expression> originalPredi

相关标签:
4条回答
  • 2020-12-14 11:18

    With Expression, the simplest way is with a conversion expression:

    class Foo {
        public int Value { get; set; }
    }
    class Bar {
        public int Value { get; set; }
    }
    static class Program {
        static void Main() {
            Expression<Func<Foo, bool>> predicate =
                x => x.Value % 2 == 0;
            Expression<Func<Bar, Foo>> convert =
                bar => new Foo { Value = bar.Value };
    
            var param = Expression.Parameter(typeof(Bar), "bar");
            var body = Expression.Invoke(predicate,
                  Expression.Invoke(convert, param));
            var lambda = Expression.Lambda<Func<Bar, bool>>(body, param);
    
            // test with LINQ-to-Objects for simplicity
            var func = lambda.Compile();
            bool withOdd = func(new Bar { Value = 7 }),
                 withEven = func(new Bar { Value = 12 });
        }
    }
    

    Note however that this will be supported differently by different providers. EF might not like it, for example, even if LINQ-to-SQL does.

    The other option is to rebuild the expression tree completely, using reflection to find the corresponding members. Much more complex.

    0 讨论(0)
  • 2020-12-14 11:26

    There is one other way I have found, that also includes wrapping your original delegate.

    Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
    {
        Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
        return g.Compile();
    }
    
    0 讨论(0)
  • 2020-12-14 11:26

    I had the same issue as you and i fixed it like this with EF:

    var viewModeValue = dbContext.Model.Select(m => new ViewModel{Field = m.Field}).Where(predicate) //predicate is an Expression<Func<ViewModel, bool>>
    

    Entity Framework knows how to build the correct sql command. Converting the expression is much more complicated, because it is built to be immutable and could cause undesired run time effects if you do something wrong, and, in my case at least, it is not needed.

    0 讨论(0)
  • 2020-12-14 11:31

    There is no implicit way to do the translation. You have to wrap your existing delegate inside a lambda that creates a new type from the argument type:

    var translatedPredicate = x => originalPredicate(OtherTypeFromSomeType(x))
    

    Where OtherTypeFromSomeType creates the OtherType instance from the SomeType argument.

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