Fun programming: Implementation of the Specification pattern in C # (reference answer

Source: Internet
Author: User
Tags bool expression

In the previous article we implemented a lightweight specification pattern using the features of the C # language, the key of which was to discard the specific specification type, instead of using a delegate object instead of the only key IsSatisfiedBy method logic. According to our analysis, one of its advantages is the use of simple, one of its disadvantages is not static representation. But they're all dealing with "business logic," and if it comes to an expression tree for LINQ queries or elsewhere, the problem is not that simple--but it's not as complicated as we think.

OK, so let's just assume the scene to LINQ. LINQ differs from ordinary business logic in that it does not use a IsSatisfiedBy method or a delegate object to represent judgment logic, but rather constructs an expression tree, a data structure. If you're not sure what the expression tree is, you can look at the hands-on guide to your head. This is an important concept from. NET 3.5, and it has been an important development in 4.0, which is a must if you want to move forward in. Net.

The easiest thing to handle between and, or and not is the not method, so we start from this place and look directly at its implementation:

public static class SpecExprExtensions
{
  public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> one)
  {
    var candidateExpr = one.Parameters[0];
    var body = Expression.Not(one.Body);

    return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
  }
}

There are two main parts in a Expression<tdelegate> object, one is the parameter and the other is the expression body. For the not method, we can construct a new expression by simply getting its argument expression and then outsourcing its body to a not expression. This part of the logic is very simple, read the head of the article, understand the basic structure of the expression tree can understand the meaning here. So experiment:

Expression<Func<int, bool>> f = i => i % 2 == 0;
f = f.Not();

foreach (var i in new int[] { 1, 2, 3, 4, 5, 6 }.AsQueryable().Where(f))
{
  Console.WriteLine(i);
}

The print out of nature is all odd, that is 1, 3, 5.

and the handling of and and or is going to be a problem, and we can't simply handle it like not:

public static Expression<Func<T, bool>> And<T>(
  this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
  var candidateExpr = one.Parameters[0];
  var body = Expression.And(one.Body, another.Body);
  return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}

While this can be compiled, it can be executed with an error. The reason is that one and another two expressions are in the same form (Expression<func<t, bool>>), but their "arguments" are not the same object. In other words, one. The body and another.body do not have a common parameterexpression instance, so regardless of which expression we use, the Expression.lambda method call will tell you the new A parameter object in the body does not appear in the argument list.

So the first thing we do if we want to implement and and or is unify the parameters of the two expression trees, so we prepare a expressionvisitor:

internal class ParameterReplacer : ExpressionVisitor
{
  public ParameterReplacer(ParameterExpression paramExpr)
  {
    this.ParameterExpression = paramExpr;
  }

  public ParameterExpression ParameterExpression { get; private set; }

  public Expression Replace(Expression expr)
  {
    return this.Visit(expr);
  }

  protected override Expression VisitParameter(ParameterExpression p)
  {
    return this.ParameterExpression;
  }
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.