Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ public IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> specific
return query.ApplySingleLike(searchExpression);
}

if (spec.OneOrManySearchExpressions.Values is List<SearchExpressionInfo<T>> list)
{
var span = CollectionsMarshal.AsSpan(list);
return ApplyLike(query, span);
}
// The search expressions are already sorted by SearchGroup.
var span = CollectionsMarshal.AsSpan(spec.OneOrManySearchExpressions.List);
return ApplyLike(query, span);
}


Expand Down
7 changes: 2 additions & 5 deletions src/Ardalis.Specification/Evaluators/SearchMemoryEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ public IEnumerable<T> Evaluate<T>(IEnumerable<T> query, ISpecification<T> specif
return new SpecSingleLikeIterator<T>(query, searchExpression);
}

if (spec.OneOrManySearchExpressions.Values is List<SearchExpressionInfo<T>> list)
{
// The search expressions are already sorted by SearchGroup.
return new SpecLikeIterator<T>(query, list);
}
// The search expressions are already sorted by SearchGroup.
return new SpecLikeIterator<T>(query, spec.OneOrManySearchExpressions.List);
}

return query;
Expand Down
25 changes: 25 additions & 0 deletions src/Ardalis.Specification/Internals/OneOrMany.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,27 @@ public void AddSorted(T item, IComparer<T> comparer)
}
}

/// <summary>
/// Gets the list value stored in the instance.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if the value is Empty or Single.</exception>
public readonly List<T> List
{
get
{
if (_value is List<T> list)
{
return list;
}

throw new InvalidOperationException("The value is not a list.");
}
}

/// <summary>
/// Gets the single value stored in the instance.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if the value is Empty or Many.</exception>
public readonly T Single
{
get
Expand All @@ -81,6 +102,10 @@ public readonly T Single
}
}

/// <summary>
/// Gets the single value stored in the instance.
/// If the value is Empty or Many, returns null.
/// </summary>
public readonly T? SingleOrDefault
{
get
Expand Down
7 changes: 2 additions & 5 deletions src/Ardalis.Specification/Validators/SearchValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@ public bool IsValid<T>(T entity, ISpecification<T> specification)
return searchExpression.SelectorFunc(entity)?.Like(searchExpression.SearchTerm) ?? false;
}

if (spec.OneOrManySearchExpressions.Values is List<SearchExpressionInfo<T>> list)
{
// The search expressions are already sorted by SearchGroup.
return IsValid<T>(entity, list);
}
// The search expressions are already sorted by SearchGroup.
return IsValid(entity, spec.OneOrManySearchExpressions.List);
}

return true;
Expand Down
29 changes: 29 additions & 0 deletions tests/Ardalis.Specification.Tests/Internals/OneOrManyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,35 @@ public void AddSorted_DoesNothing_GivenInvalidState()
value.Should().BeEquivalentTo(new string[] { "foo", "bar" });
}

[Fact]
public void List_ReturnsList_GivenMultipleItems()
{
var oneOrMany = new OneOrMany<string>();
Accessors.ValueOf(ref oneOrMany) = new List<string> { "foo", "bar" };

oneOrMany.List.Should().BeOfType<List<string>>();
oneOrMany.List.Should().Equal(new List<string> { "foo", "bar" });
}

[Fact]
public void List_Throws_GivenEmptyStruct()
{
var oneOrMany = new OneOrMany<string>();

var action = () => oneOrMany.List;
action.Should().Throw<InvalidOperationException>();
}

[Fact]
public void List_Throws_GivenSingleItem()
{
var oneOrMany = new OneOrMany<string>();
Accessors.ValueOf(ref oneOrMany) = "foo";

var action = () => _ = oneOrMany.List;
action.Should().Throw<InvalidOperationException>();
}

[Fact]
public void Single_ReturnsSingleItem_GivenSingleItem()
{
Expand Down