using System; using System.Linq; using System.Linq.Expressions; namespace UserManagement.Helper { public class GenericSpecification { private readonly Expression> expression; public GenericSpecification(Expression> _expression) { this.expression = _expression; } public bool IsSatifiedBy(T entity) { return this.expression.Compile().Invoke(entity); } } internal sealed class IdentificationSpecification : Specification { public override Expression> ExpressionTo() { return x => true; } } public abstract class Specification { public static readonly Specification All = new IdentificationSpecification(); public bool IsSatified(T entity) { Func predicate = this.ExpressionTo().Compile(); return predicate.Invoke(entity); } public abstract Expression> ExpressionTo(); public Specification And(Specification specification) { if (this == All) return specification; if (specification == All) return this; return new AndSpecification(this, specification); } public Specification Or(Specification specification) { if (this == All || specification == All) return All; return new OrSpecification(this, specification); } public Specification Not(Specification specification) { return new NotSpecification(this); } } internal sealed class AndSpecification : Specification { private readonly Specification left; private readonly Specification right; public AndSpecification(Specification _left, Specification _right) { left = _left; right = _right; } public override Expression> ExpressionTo() { Expression> leftPredicate = left.ExpressionTo(); Expression> rightPredicate = right.ExpressionTo(); BinaryExpression andExpression = Expression.AndAlso(leftPredicate.Body, rightPredicate.Body); return Expression.Lambda>(andExpression, leftPredicate.Parameters.Single()); } } internal sealed class OrSpecification : Specification { private readonly Specification left; private readonly Specification right; public OrSpecification(Specification _left, Specification _right) { left = _left; right = _right; } public override Expression> ExpressionTo() { Expression> leftPredicate = left.ExpressionTo(); Expression> rightPredicate = right.ExpressionTo(); BinaryExpression expression = Expression.OrElse(leftPredicate.Body, rightPredicate.Body); return Expression.Lambda>(expression, leftPredicate.Parameters.Single()); } } internal sealed class NotSpecification:Specification { private readonly Specification specification; public NotSpecification(Specification _specification) { specification = _specification; } public override Expression> ExpressionTo() { Expression> predicate= specification.ExpressionTo(); UnaryExpression expression = Expression.Not(predicate.Body); return Expression.Lambda>(expression, predicate.Parameters.Single()); } } }