170 lines
6.7 KiB
C#
170 lines
6.7 KiB
C#
|
using System.Linq.Expressions;
|
|||
|
using ZeroFramework.DeviceCenter.Domain.Specifications.Exceptions;
|
|||
|
|
|||
|
namespace ZeroFramework.DeviceCenter.Domain.Specifications.Builder
|
|||
|
{
|
|||
|
public static class SpecificationBuilderExtensions
|
|||
|
{
|
|||
|
public static ISpecificationBuilder<T> Where<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
Expression<Func<T, bool>> criteria)
|
|||
|
{
|
|||
|
((List<Expression<Func<T, bool>>>)specificationBuilder.Specification.WhereExpressions).Add(criteria);
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static IOrderedSpecificationBuilder<T> OrderBy<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
Expression<Func<T, object?>> orderExpression)
|
|||
|
{
|
|||
|
((List<(Expression<Func<T, object?>> OrderExpression, OrderTypeEnum OrderType)>)specificationBuilder.Specification.OrderExpressions)
|
|||
|
.Add((orderExpression, OrderTypeEnum.OrderBy));
|
|||
|
|
|||
|
var orderedSpecificationBuilder = new OrderedSpecificationBuilder<T>(specificationBuilder.Specification);
|
|||
|
|
|||
|
return orderedSpecificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static IOrderedSpecificationBuilder<T> OrderByDescending<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
Expression<Func<T, object?>> orderExpression)
|
|||
|
{
|
|||
|
((List<(Expression<Func<T, object?>> OrderExpression, OrderTypeEnum OrderType)>)specificationBuilder.Specification.OrderExpressions)
|
|||
|
.Add((orderExpression, OrderTypeEnum.OrderByDescending));
|
|||
|
|
|||
|
var orderedSpecificationBuilder = new OrderedSpecificationBuilder<T>(specificationBuilder.Specification);
|
|||
|
|
|||
|
return orderedSpecificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static IIncludableSpecificationBuilder<T, TProperty> Include<T, TProperty>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
Expression<Func<T, TProperty>> includeExpression) where T : class
|
|||
|
{
|
|||
|
var info = new IncludeExpressionInfo(includeExpression, typeof(T), typeof(TProperty));
|
|||
|
|
|||
|
((List<IncludeExpressionInfo>)specificationBuilder.Specification.IncludeExpressions).Add(info);
|
|||
|
|
|||
|
var includeBuilder = new IncludableSpecificationBuilder<T, TProperty>(specificationBuilder.Specification);
|
|||
|
|
|||
|
return includeBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> Include<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
string includeString) where T : class
|
|||
|
{
|
|||
|
((List<string>)specificationBuilder.Specification.IncludeStrings).Add(includeString);
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> Search<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
Expression<Func<T, string>> selector,
|
|||
|
string searchTerm,
|
|||
|
int searchGroup = 1) where T : class
|
|||
|
{
|
|||
|
((List<(Expression<Func<T, string>> Selector, string SearchTerm, int SearchGroup)>)specificationBuilder.Specification.SearchCriterias)
|
|||
|
.Add((selector, searchTerm, searchGroup));
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> Take<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
int take)
|
|||
|
{
|
|||
|
if (specificationBuilder.Specification.Take != null) throw new DuplicateTakeException();
|
|||
|
|
|||
|
specificationBuilder.Specification.Take = take;
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> Skip<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
int skip)
|
|||
|
{
|
|||
|
if (specificationBuilder.Specification.Skip != null) throw new DuplicateSkipException();
|
|||
|
|
|||
|
specificationBuilder.Specification.Skip = skip;
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> PostProcessingAction<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder,
|
|||
|
Func<IEnumerable<T>, IEnumerable<T>> predicate)
|
|||
|
{
|
|||
|
specificationBuilder.Specification.PostProcessingAction = predicate;
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T, TResult> Select<T, TResult>(
|
|||
|
this ISpecificationBuilder<T, TResult> specificationBuilder,
|
|||
|
Expression<Func<T, TResult>> selector)
|
|||
|
{
|
|||
|
specificationBuilder.Specification.Selector = selector;
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T, TResult> PostProcessingAction<T, TResult>(
|
|||
|
this ISpecificationBuilder<T, TResult> specificationBuilder,
|
|||
|
Func<IEnumerable<TResult>, IEnumerable<TResult>> predicate)
|
|||
|
{
|
|||
|
specificationBuilder.Specification.PostProcessingAction = predicate;
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Must be called after specifying criteria
|
|||
|
/// </summary>
|
|||
|
/// <param name="specificationName"></param>
|
|||
|
/// <param name="args">Any arguments used in defining the specification</param>
|
|||
|
public static ICacheSpecificationBuilder<T> EnableCache<T>(
|
|||
|
this ISpecificationBuilder<T> 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<T>(specificationBuilder.Specification);
|
|||
|
|
|||
|
return cacheBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> AsNoTracking<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder) where T : class
|
|||
|
{
|
|||
|
specificationBuilder.Specification.AsNoTracking = true;
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> AsSplitQuery<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder) where T : class
|
|||
|
{
|
|||
|
specificationBuilder.Specification.AsSplitQuery = true;
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
|
|||
|
public static ISpecificationBuilder<T> AsNoTrackingWithIdentityResolution<T>(
|
|||
|
this ISpecificationBuilder<T> specificationBuilder) where T : class
|
|||
|
{
|
|||
|
specificationBuilder.Specification.AsNoTrackingWithIdentityResolution = true;
|
|||
|
|
|||
|
return specificationBuilder;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|