Как создать дерево выражений, чтобы сделать так же, как "StartsWith" - PullRequest
7 голосов
/ 29 декабря 2010

В настоящее время у меня есть этот метод для сравнения двух чисел

Private Function ETForGreaterThan(ByVal query As IQueryable(Of T), ByVal propertyValue As Object, ByVal propertyInfo As PropertyInfo) As IQueryable(Of T)

    Dim e As ParameterExpression = Expression.Parameter(GetType(T), "e")
    Dim m As MemberExpression = Expression.MakeMemberAccess(e, propertyInfo)
    Dim c As ConstantExpression = Expression.Constant(propertyValue, propertyValue.GetType())
    Dim b As BinaryExpression = Expression.GreaterThan(m, c)
    Dim lambda As Expression(Of Func(Of T, Boolean)) = Expression.Lambda(Of Func(Of T, Boolean))(b, e)
    Return query.Where(lambda)

End Function

Работает нормально и потребляется таким образом

query = ETForGreaterThan(query, Value, propertyInfo)

Как видите, я даю ему коллекцию IQueryable, и она добавляет к ней предложение where, основанное на свойстве и значении. Y может создавать эквиваленты Lessthan, LessOrEqualThan и т. Д., Так как System.Linq.Expressions.Expression имеет эти предопределенные операторы.

¿Как я могу преобразовать этот код, чтобы сделать то же самое со строками? System.Linq.Expressions.Expression не дает мне предопределенный оператор, такой как «contains» или «startwith», и я действительно нуб с деревьями выражений.

Спасибо, и, пожалуйста, оставьте свой ответ на C # / VB. Выберите тот, который заставляет вас чувствовать себя более комфортно.

Ответы [ 2 ]

18 голосов
/ 29 декабря 2010
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace WindowsFormsApplication1
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            using (var context = new NorthwindEntities())
            {
                PropertyInfo propertyInfo = typeof(Customer).GetProperty("CustomerID"); 

                IQueryable<Customer> query = context.Customers;
                query = ETForStartsWith<Customer>(query, "A", propertyInfo); 
                var list = query.ToList();
            }
        }

        static IQueryable<T> ETForStartsWith<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo)
        {
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
            ConstantExpression c = Expression.Constant(propertyValue, typeof(string));
            MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
            Expression call = Expression.Call(m, mi, c);

            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, e); 
            return query.Where(lambda);
        }
    }
}
4 голосов
/ 29 декабря 2010

Это не оператор, а метод, поэтому вы можете вызвать его с помощью Expression.Call (), где параметром methodinfo будет typeof (string) .GetMethod ("StartsWith").

...