using System.Linq.Expressions; using ZeroFramework.DeviceCenter.Domain.Specifications.Exceptions; namespace ZeroFramework.DeviceCenter.Domain.Specifications.Builder { public static class SpecificationBuilderExtensions { public static ISpecificationBuilder Where( this ISpecificationBuilder specificationBuilder, Expression> criteria) { ((List>>)specificationBuilder.Specification.WhereExpressions).Add(criteria); return specificationBuilder; } public static IOrderedSpecificationBuilder OrderBy( this ISpecificationBuilder specificationBuilder, Expression> orderExpression) { ((List<(Expression> OrderExpression, OrderTypeEnum OrderType)>)specificationBuilder.Specification.OrderExpressions) .Add((orderExpression, OrderTypeEnum.OrderBy)); var orderedSpecificationBuilder = new OrderedSpecificationBuilder(specificationBuilder.Specification); return orderedSpecificationBuilder; } public static IOrderedSpecificationBuilder OrderByDescending( this ISpecificationBuilder specificationBuilder, Expression> orderExpression) { ((List<(Expression> OrderExpression, OrderTypeEnum OrderType)>)specificationBuilder.Specification.OrderExpressions) .Add((orderExpression, OrderTypeEnum.OrderByDescending)); var orderedSpecificationBuilder = new OrderedSpecificationBuilder(specificationBuilder.Specification); return orderedSpecificationBuilder; } public static IIncludableSpecificationBuilder Include( this ISpecificationBuilder specificationBuilder, Expression> includeExpression) where T : class { var info = new IncludeExpressionInfo(includeExpression, typeof(T), typeof(TProperty)); ((List)specificationBuilder.Specification.IncludeExpressions).Add(info); var includeBuilder = new IncludableSpecificationBuilder(specificationBuilder.Specification); return includeBuilder; } public static ISpecificationBuilder Include( this ISpecificationBuilder specificationBuilder, string includeString) where T : class { ((List)specificationBuilder.Specification.IncludeStrings).Add(includeString); return specificationBuilder; } public static ISpecificationBuilder Search( this ISpecificationBuilder specificationBuilder, Expression> selector, string searchTerm, int searchGroup = 1) where T : class { ((List<(Expression> Selector, string SearchTerm, int SearchGroup)>)specificationBuilder.Specification.SearchCriterias) .Add((selector, searchTerm, searchGroup)); return specificationBuilder; } public static ISpecificationBuilder Take( this ISpecificationBuilder specificationBuilder, int take) { if (specificationBuilder.Specification.Take != null) throw new DuplicateTakeException(); specificationBuilder.Specification.Take = take; return specificationBuilder; } public static ISpecificationBuilder Skip( this ISpecificationBuilder specificationBuilder, int skip) { if (specificationBuilder.Specification.Skip != null) throw new DuplicateSkipException(); specificationBuilder.Specification.Skip = skip; return specificationBuilder; } public static ISpecificationBuilder PostProcessingAction( this ISpecificationBuilder specificationBuilder, Func, IEnumerable> predicate) { specificationBuilder.Specification.PostProcessingAction = predicate; return specificationBuilder; } public static ISpecificationBuilder Select( this ISpecificationBuilder specificationBuilder, Expression> selector) { specificationBuilder.Specification.Selector = selector; return specificationBuilder; } public static ISpecificationBuilder PostProcessingAction( this ISpecificationBuilder specificationBuilder, Func, IEnumerable> predicate) { specificationBuilder.Specification.PostProcessingAction = predicate; return specificationBuilder; } /// /// Must be called after specifying criteria /// /// /// Any arguments used in defining the specification public static ICacheSpecificationBuilder EnableCache( this ISpecificationBuilder specificationBuilder, string specificationName, params object[] args) where T : class { if (string.IsNullOrEmpty(specificationName)) { throw new ArgumentException($"Required input {specificationName} was null or empty.", specificationName); } specificationBuilder.Specification.CacheKey = $"{specificationName}-{string.Join("-", args)}"; specificationBuilder.Specification.CacheEnabled = true; var cacheBuilder = new CacheSpecificationBuilder(specificationBuilder.Specification); return cacheBuilder; } public static ISpecificationBuilder AsNoTracking( this ISpecificationBuilder specificationBuilder) where T : class { specificationBuilder.Specification.AsNoTracking = true; return specificationBuilder; } public static ISpecificationBuilder AsSplitQuery( this ISpecificationBuilder specificationBuilder) where T : class { specificationBuilder.Specification.AsSplitQuery = true; return specificationBuilder; } public static ISpecificationBuilder AsNoTrackingWithIdentityResolution( this ISpecificationBuilder specificationBuilder) where T : class { specificationBuilder.Specification.AsNoTrackingWithIdentityResolution = true; return specificationBuilder; } } }