Created
April 10, 2018 19:44
-
-
Save hkakutalua/8c293668a1a5946fdd1c83fab9ca9fcd to your computer and use it in GitHub Desktop.
Querying using specification pattern
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| private async Task<Passenger> GetPermanentPassengerByPhoneNumber(PhoneNumberViewModel phoneNumberVM) | |
| { | |
| var phoneNumber = new PhoneNumber(phoneNumberVM.CountryCode, phoneNumberVM.Number); | |
| var phoneCriteria = new PassengerByPhoneSpecification(phoneNumber); | |
| var permanentPassengerCriteria = new PermanentPassengerSpecification(); | |
| return await _passengerRepository.FindOne( | |
| phoneCriteria.AndSpecification(permanentPassengerCriteria)); | |
| } | |
| public class PassengerByPhoneSpecification : Specification<Passenger> | |
| { | |
| private readonly PhoneNumber _phoneNumber; | |
| public PassengerByPhoneSpecification(PhoneNumber phoneNumber) | |
| { | |
| if (phoneNumber == null) | |
| throw new ArgumentNullException(); | |
| _phoneNumber = phoneNumber; | |
| } | |
| public override Expression<Func<Passenger, bool>> ToExpression() | |
| { | |
| return passenger => passenger.PhoneNumber == _phoneNumber; | |
| } | |
| } | |
| public class PermanentPassengerSpecification : Specification<Passenger> | |
| { | |
| public override Expression<Func<Passenger, bool>> ToExpression() | |
| { | |
| return passenger => passenger.EmailConfirmed == true; | |
| } | |
| } | |
| public abstract class Specification<TEntity> | |
| where TEntity : class | |
| { | |
| public abstract Expression<Func<TEntity, bool>> ToExpression(); | |
| public bool IsSatisfiedBy(TEntity entity) | |
| { | |
| Func<TEntity, bool> predicate = ToExpression().Compile(); | |
| return predicate(entity); | |
| } | |
| public Specification<TEntity> AndSpecification(Specification<TEntity> specification) | |
| { | |
| return new AndSpecification<TEntity>(this, specification); | |
| } | |
| public Specification<TEntity> OrSpecification(Specification<TEntity> specification) | |
| { | |
| return new OrSpecification<TEntity>(this, specification); | |
| } | |
| } | |
| public class AndSpecification<TEntity> : Specification<TEntity> | |
| where TEntity : class | |
| { | |
| private readonly Specification<TEntity> _left; | |
| private readonly Specification<TEntity> _right; | |
| public AndSpecification(Specification<TEntity> left, Specification<TEntity> right) | |
| { | |
| _left = left; | |
| _right = right; | |
| } | |
| public override Expression<Func<TEntity, bool>> ToExpression() | |
| { | |
| Expression<Func<TEntity, bool>> leftExpression = _left.ToExpression(); | |
| Expression<Func<TEntity, bool>> rightExpression = _right.ToExpression(); | |
| var paramExpr = Expression.Parameter(typeof(TEntity)); | |
| var exprBody = Expression.AndAlso(leftExpression.Body, rightExpression.Body); | |
| exprBody = (BinaryExpression)new ParameterReplacer(paramExpr).Visit(exprBody); | |
| var finalExpr = Expression.Lambda<Func<TEntity, bool>>(exprBody, paramExpr); | |
| return finalExpr; | |
| } | |
| } | |
| public class OrSpecification<TEntity> : Specification<TEntity> | |
| where TEntity : class | |
| { | |
| private readonly Specification<TEntity> _left; | |
| private readonly Specification<TEntity> _right; | |
| public OrSpecification(Specification<TEntity> left, Specification<TEntity> right) | |
| { | |
| _left = left; | |
| _right = right; | |
| } | |
| public override Expression<Func<TEntity, bool>> ToExpression() | |
| { | |
| Expression<Func<TEntity, bool>> leftExpression = _left.ToExpression(); | |
| Expression<Func<TEntity, bool>> rightExpression = _right.ToExpression(); | |
| var paramExpr = Expression.Parameter(typeof(TEntity)); | |
| var exprBody = Expression.OrElse(leftExpression.Body, rightExpression.Body); | |
| exprBody = (BinaryExpression)new ParameterReplacer(paramExpr).Visit(exprBody); | |
| var finalExpr = Expression.Lambda<Func<TEntity, bool>>(exprBody, paramExpr); | |
| return finalExpr; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment