Skip to content

Commit

Permalink
Simplify and minimize expression containers. (#448)
Browse files Browse the repository at this point in the history
  • Loading branch information
fiseni authored Mar 9, 2025
1 parent c74af2c commit db5849c
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public static IQueryable<T> Include<T>(this IQueryable<T> source, IncludeExpress
public static IQueryable<T> ThenInclude<T>(this IQueryable<T> source, IncludeExpressionInfo info)
{
_ = info ?? throw new ArgumentNullException(nameof(info));
_ = info.PreviousPropertyType ?? throw new ArgumentNullException(nameof(info.PreviousPropertyType));

var exp = source.Expression as MethodCallExpression;
var arg = exp.Arguments[0] as ConstantExpression;
Expand Down Expand Up @@ -47,7 +46,7 @@ public static IQueryable<T> ThenInclude<T>(this IQueryable<T> source, IncludeExp
return QueryableExtensions.Include(source, $"{previousPropertyName}.{propertyName}");
}

private static string GetPropertyName(this Expression propertySelector, char delimiter = '.', char endTrim = ')')
private static string GetPropertyName(this LambdaExpression propertySelector, char delimiter = '.', char endTrim = ')')
{

var asString = propertySelector.ToString();
Expand Down
12 changes: 6 additions & 6 deletions src/Ardalis.Specification/Builders/Builder_Include.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public static IIncludableSpecificationBuilder<T, TResult, TProperty> Include<T,
{
if (condition)
{
var expr = new IncludeExpressionInfo(navigationSelector, typeof(T), typeof(TProperty));
var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.Include);
builder.Specification.Add(expr);
}

Expand Down Expand Up @@ -139,7 +139,7 @@ public static IIncludableSpecificationBuilder<T, TProperty> Include<T, TProperty
{
if (condition)
{
var expr = new IncludeExpressionInfo(navigationSelector, typeof(T), typeof(TProperty));
var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.Include);
builder.Specification.Add(expr);
}

Expand Down Expand Up @@ -183,7 +183,7 @@ public static IIncludableSpecificationBuilder<TEntity, TResult, TProperty> ThenI
{
if (condition && !Specification<TEntity, TResult>.IsChainDiscarded)
{
var expr = new IncludeExpressionInfo(navigationSelector, typeof(TEntity), typeof(TProperty), typeof(TPreviousProperty));
var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude);
builder.Specification.Add(expr);
}
else
Expand Down Expand Up @@ -228,7 +228,7 @@ public static IIncludableSpecificationBuilder<TEntity, TProperty> ThenInclude<TE
{
if (condition && !Specification<TEntity>.IsChainDiscarded)
{
var expr = new IncludeExpressionInfo(navigationSelector, typeof(TEntity), typeof(TProperty), typeof(TPreviousProperty));
var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude);
builder.Specification.Add(expr);
}
else
Expand Down Expand Up @@ -275,7 +275,7 @@ public static IIncludableSpecificationBuilder<TEntity, TResult, TProperty> ThenI
{
if (condition && !Specification<TEntity, TResult>.IsChainDiscarded)
{
var expr = new IncludeExpressionInfo(navigationSelector, typeof(TEntity), typeof(TProperty), typeof(IEnumerable<TPreviousProperty>));
var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude);
builder.Specification.Add(expr);
}
else
Expand Down Expand Up @@ -320,7 +320,7 @@ public static IIncludableSpecificationBuilder<TEntity, TProperty> ThenInclude<TE
{
if (condition && !Specification<TEntity>.IsChainDiscarded)
{
var expr = new IncludeExpressionInfo(navigationSelector, typeof(TEntity), typeof(TProperty), typeof(IEnumerable<TPreviousProperty>));
var expr = new IncludeExpressionInfo(navigationSelector, IncludeTypeEnum.ThenInclude);
builder.Specification.Add(expr);
}
else
Expand Down
62 changes: 1 addition & 61 deletions src/Ardalis.Specification/Expressions/IncludeExpressionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,76 +11,16 @@ public class IncludeExpressionInfo
/// </summary>
public LambdaExpression LambdaExpression { get; }

/// <summary>
/// The type of the source entity.
/// </summary>
public Type EntityType { get; }

/// <summary>
/// The type of the included entity.
/// </summary>
public Type PropertyType { get; }

/// <summary>
/// The type of the previously included entity.
/// </summary>
public Type? PreviousPropertyType { get; }

/// <summary>
/// The include type.
/// </summary>
public IncludeTypeEnum Type { get; }

private IncludeExpressionInfo(LambdaExpression expression,
Type entityType,
Type propertyType,
Type? previousPropertyType,
IncludeTypeEnum includeType)

public IncludeExpressionInfo(LambdaExpression expression, IncludeTypeEnum includeType)
{
_ = expression ?? throw new ArgumentNullException(nameof(expression));
_ = entityType ?? throw new ArgumentNullException(nameof(entityType));
_ = propertyType ?? throw new ArgumentNullException(nameof(propertyType));

if (includeType == IncludeTypeEnum.ThenInclude)
{
_ = previousPropertyType ?? throw new ArgumentNullException(nameof(previousPropertyType));
}

LambdaExpression = expression;
EntityType = entityType;
PropertyType = propertyType;
PreviousPropertyType = previousPropertyType;
Type = includeType;
}

/// <summary>
/// Creates instance of <see cref="IncludeExpressionInfo" /> which describes 'Include' query part.<para />
/// Source (entityType) -> Include (propertyType).
/// </summary>
/// <param name="expression">The expression represents a related entity that should be included.</param>
/// <param name="entityType">The type of the source entity.</param>
/// <param name="propertyType">The type of the included entity.</param>
public IncludeExpressionInfo(LambdaExpression expression,
Type entityType,
Type propertyType)
: this(expression, entityType, propertyType, null, IncludeTypeEnum.Include)
{
}

/// <summary>
/// Creates instance of <see cref="IncludeExpressionInfo" /> which describes 'ThenInclude' query part.<para />
/// Source (entityType) -> Include (previousPropertyType) -> ThenInclude (propertyType).
/// </summary>
/// <param name="expression">The expression represents a related entity that should be included as part of the previously included entity.</param>
/// <param name="entityType">The type of the source entity.</param>
/// <param name="propertyType">The type of the included entity.</param>
/// <param name="previousPropertyType">The type of the previously included entity.</param>
public IncludeExpressionInfo(LambdaExpression expression,
Type entityType,
Type propertyType,
Type previousPropertyType)
: this(expression, entityType, propertyType, previousPropertyType, IncludeTypeEnum.ThenInclude)
{
}
}
6 changes: 2 additions & 4 deletions src/Ardalis.Specification/Expressions/OrderExpressionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <typeparam name="T">Type of the entity to apply sort on.</typeparam>
public class OrderExpressionInfo<T>
{
private readonly Lazy<Func<T, object?>> _keySelectorFunc;
private Func<T, object?>? _keySelectorFunc;

/// <summary>
/// Creates instance of <see cref="OrderExpressionInfo{T}" />.
Expand All @@ -20,8 +20,6 @@ public OrderExpressionInfo(Expression<Func<T, object?>> keySelector, OrderTypeEn

KeySelector = keySelector;
OrderType = orderType;

_keySelectorFunc = new Lazy<Func<T, object?>>(KeySelector.Compile);
}

/// <summary>
Expand All @@ -37,5 +35,5 @@ public OrderExpressionInfo(Expression<Func<T, object?>> keySelector, OrderTypeEn
/// <summary>
/// Compiled <see cref="KeySelector" />.
/// </summary>
public Func<T, object?> KeySelectorFunc => _keySelectorFunc.Value;
public Func<T, object?> KeySelectorFunc => _keySelectorFunc ??= KeySelector.Compile();
}
6 changes: 2 additions & 4 deletions src/Ardalis.Specification/Expressions/SearchExpressionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <typeparam name="T">Type of the source from which search target should be selected.</typeparam>
public class SearchExpressionInfo<T>
{
private readonly Lazy<Func<T, string?>> _selectorFunc;
private Func<T, string?>? _selectorFunc;

/// <summary>
/// Creates instance of <see cref="SearchExpressionInfo{T}" />.
Expand All @@ -24,8 +24,6 @@ public SearchExpressionInfo(Expression<Func<T, string?>> selector, string search
Selector = selector;
SearchTerm = searchTerm;
SearchGroup = searchGroup;

_selectorFunc = new Lazy<Func<T, string?>>(Selector.Compile);
}

/// <summary>
Expand All @@ -46,5 +44,5 @@ public SearchExpressionInfo(Expression<Func<T, string?>> selector, string search
/// <summary>
/// Compiled <see cref="Selector" />.
/// </summary>
public Func<T, string?> SelectorFunc => _selectorFunc.Value;
public Func<T, string?> SelectorFunc => _selectorFunc ??= Selector.Compile();
}
7 changes: 2 additions & 5 deletions src/Ardalis.Specification/Expressions/WhereExpressionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <typeparam name="T">Type of the entity to apply filter on.</typeparam>
public class WhereExpressionInfo<T>
{
private readonly Lazy<Func<T, bool>> _filterFunc;
private Func<T, bool>? _filterFunc;

/// <summary>
/// Creates instance of <see cref="WhereExpressionInfo{T}" />.
Expand All @@ -16,10 +16,7 @@ public class WhereExpressionInfo<T>
public WhereExpressionInfo(Expression<Func<T, bool>> filter)
{
_ = filter ?? throw new ArgumentNullException(nameof(filter));

Filter = filter;

_filterFunc = new Lazy<Func<T, bool>>(Filter.Compile);
}

/// <summary>
Expand All @@ -30,5 +27,5 @@ public WhereExpressionInfo(Expression<Func<T, bool>> filter)
/// <summary>
/// Compiled <see cref="Filter" />.
/// </summary>
public Func<T, bool> FilterFunc => _filterFunc.Value;
public Func<T, bool> FilterFunc => _filterFunc ??= Filter.Compile();
}

0 comments on commit db5849c

Please sign in to comment.