SORU
19 Ocak 2009, PAZARTESİ


İki ifadeyi (İfade<İşlev<T, bool>>)birleştiren

6 ** iki tip ifadeler var YA, al VE ya bu DEĞİL ve aynı türde yeni bir ifade almak istiyorum

Expression<Func<T, bool>> expr1;
Expression<Func<T, bool>> expr2;

...

//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2

CEVAP
19 Ocak 2009, PAZARTESİ


İyi, Expression.AndAlso / OrElse vb mantıksal ifadeleri birleştirmek için kullanabilirsiniz, ama sorun parametreleri; expr1 ve expr2 ParameterExpression aynı çalışma misin? Eğer öyleyse, bu kolaydır:

var body = Expression.AndAlso(expr1.Body, expr2.Body);
var lambda = Expression.Lambda<Func<T,bool>>(body, expr1.Parameters[0]);

Bu da tek bir işlemle inkar etmeye çalışır:

static Expression<Func<T, bool>> Not<T>(
    this Expression<Func<T, bool>> expr)
{
    return Expression.Lambda<Func<T, bool>>(
        Expression.Not(expr.Body), expr.Parameters[0]);
}

Aksi takdirde, SERİ sağlayıcısına bağlı olarak, Invoke ile onları birleştirmek mümkün olabilir:

// OrElse is very similar...
static Expression<Func<T, bool>> AndAlso<T>(
    this Expression<Func<T, bool>> left,
    Expression<Func<T, bool>> right)
{
    var param = Expression.Parameter(typeof(T), "x");
    var body = Expression.AndAlso(
            Expression.Invoke(left, param),
            Expression.Invoke(right, param)
        );
    var lambda = Expression.Lambda<Func<T, bool>>(body, param);
    return lambda;
}

Bir yerlerde, ben bir kod yeniden yazma bir ifade ağacı yerine düğümleri kaldırmak lazım Invoke, ama oldukça uzun (ve ben hatırlayamıyorum koymuş gibi...)


Genelleştirilmiş en basit yolu seçer sürüm:

static Expression<Func<T, bool>> AndAlso<T>(
    this Expression<Func<T, bool>> expr1,
    Expression<Func<T, bool>> expr2)
{
    // need to detect whether they use the same
    // parameter instance; if not, they need fixing
    ParameterExpression param = expr1.Parameters[0];
    if (ReferenceEquals(param, expr2.Parameters[0]))
    {
        // simple version
        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(expr1.Body, expr2.Body), param);
    }
    // otherwise, keep expr1 "as is" and invoke expr2
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(
            expr1.Body,
            Expression.Invoke(expr2, param)), param);
}

Başlatılmasını .net 4.0. EF güvenli olan ifadeleri oluşturmak için izin ExpressionVistor sınıfı var.

    public static Expression<Func<T, bool>> AndAlso<T>(
        this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        var parameter = Expression.Parameter(typeof (T));

        var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
        var left = leftVisitor.Visit(expr1.Body);

        var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
        var right = rightVisitor.Visit(expr2.Body);

        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(left, right), parameter);
    }



    private class ReplaceExpressionVisitor
        : ExpressionVisitor
    {
        private readonly Expression _oldValue;
        private readonly Expression _newValue;

        public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
        {
            _oldValue = oldValue;
            _newValue = newValue;
        }

        public override Expression Visit(Expression node)
        {
            if (node == _oldValue)
                return _newValue;
            return base.Visit(node);
        }
    }

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ADDVOiCE

    ADDVOiCE

    28 Mayıs 2009
  • CruzerLite

    CruzerLite

    1 EKİM 2011
  • Megan Parken

    Megan Parken

    19 Temmuz 2009