-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding Except and Union descriptors (#42)
* Adding Except and Union descriptors * Release notes.
- Loading branch information
Showing
12 changed files
with
219 additions
and
16 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
142 changes: 142 additions & 0 deletions
142
LogicBuilder.EntityFrameworkCore.SqlServer.Tests/CollectionExpressionTests.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
using AutoMapper; | ||
using AutoMapper.Extensions.ExpressionMapping; | ||
using LogicBuilder.EntityFrameworkCore.SqlServer.Mapping; | ||
using LogicBuilder.EntityFrameworkCore.SqlServer.Tests.Data; | ||
using LogicBuilder.Expressions.Utils.ExpressionBuilder.Lambda; | ||
using LogicBuilder.Expressions.Utils.ExpressionDescriptors; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Linq.Expressions; | ||
using Xunit; | ||
|
||
namespace LogicBuilder.EntityFrameworkCore.SqlServer.Tests | ||
{ | ||
public class CollectionExpressionTests | ||
{ | ||
public CollectionExpressionTests() | ||
{ | ||
Initialize(); | ||
} | ||
|
||
#region Fields | ||
private IServiceProvider serviceProvider; | ||
private static readonly string parameterName = "$it"; | ||
#endregion Fields | ||
|
||
[Fact] | ||
public void ConcatDescriptorWorks() | ||
{ | ||
//act | ||
var descriptor = new ConcatDescriptor | ||
( | ||
new MemberSelectorDescriptor("AlternateAddresses", new ParameterDescriptor(parameterName)), | ||
new ConstantDescriptor(new Address[] { new Address { City = "Seattle" }, new Address { City = "Portland" } }) | ||
); | ||
var expression = GetExpression<Product, IEnumerable<Address>>(descriptor); | ||
var result = RunExpression | ||
( | ||
expression, | ||
new Product { AlternateAddresses = new[] { new Address { City = "Redmond" }, new Address { City = "Seattle" } } } | ||
); | ||
|
||
AssertExpressionStringIsCorrect(expression, "$it => $it.AlternateAddresses.Concat(LogicBuilder.EntityFrameworkCore.SqlServer.Tests.Data.Address[])"); | ||
Assert.Equal(4, result.Count()); | ||
} | ||
|
||
[Fact] | ||
public void ExceptDescriptorWorks() | ||
{ | ||
//act | ||
var descriptor = new ExceptDescriptor | ||
( | ||
new MemberSelectorDescriptor("AlternateAddresses", new ParameterDescriptor(parameterName)), | ||
new ConstantDescriptor(new Address[] { new Address { City = "Seattle" }, new Address { City = "Portland" } }) | ||
); | ||
var expression = GetExpression<Product, IEnumerable<Address>>(descriptor); | ||
var result = RunExpression | ||
( | ||
expression, | ||
new Product { AlternateAddresses = new[] { new Address { City = "Redmond" }, new Address { City = "Seattle" } } } | ||
); | ||
|
||
AssertExpressionStringIsCorrect(expression, "$it => $it.AlternateAddresses.Except(LogicBuilder.EntityFrameworkCore.SqlServer.Tests.Data.Address[])"); | ||
Assert.Single(result); | ||
Assert.Equal(new Address { City = "Redmond" }, result.Single()); | ||
} | ||
|
||
[Fact] | ||
public void UnionDescriptorWorks() | ||
{ | ||
//act | ||
var descriptor = new UnionDescriptor | ||
( | ||
new MemberSelectorDescriptor("AlternateAddresses", new ParameterDescriptor(parameterName)), | ||
new ConstantDescriptor(new Address[] { new Address { City = "Seattle" }, new Address { City = "Portland" } }) | ||
); | ||
var expression = GetExpression<Product, IEnumerable<Address>>(descriptor); | ||
var result = RunExpression | ||
( | ||
expression, | ||
new Product { AlternateAddresses = new[] { new Address { City = "Redmond" }, new Address { City = "Seattle" } } } | ||
); | ||
|
||
AssertExpressionStringIsCorrect(expression, "$it => $it.AlternateAddresses.Union(LogicBuilder.EntityFrameworkCore.SqlServer.Tests.Data.Address[])"); | ||
Assert.Equal(3, result.Count()); | ||
} | ||
|
||
static MapperConfiguration MapperConfiguration; | ||
private void Initialize() | ||
{ | ||
MapperConfiguration ??= new MapperConfiguration(cfg => | ||
{ | ||
cfg.AddExpressionMapping(); | ||
cfg.AddProfile<ExpressionOperatorsMappingProfile>(); | ||
}); | ||
|
||
serviceProvider = new ServiceCollection() | ||
.AddSingleton<AutoMapper.IConfigurationProvider> | ||
( | ||
MapperConfiguration | ||
) | ||
.AddTransient<IMapper>(sp => new Mapper(sp.GetRequiredService<AutoMapper.IConfigurationProvider>(), sp.GetService)) | ||
.BuildServiceProvider(); | ||
} | ||
|
||
private static IDictionary<string, ParameterExpression> GetParameters() | ||
=> new Dictionary<string, ParameterExpression>(); | ||
|
||
private Expression<Func<T, TResult>> GetExpression<T, TResult>(IExpressionDescriptor filterBody, string parameterName = "$it") | ||
{ | ||
IMapper mapper = serviceProvider.GetRequiredService<IMapper>(); | ||
|
||
return (Expression<Func<T, TResult>>)mapper.Map<SelectorLambdaOperator> | ||
( | ||
new SelectorLambdaDescriptor | ||
( | ||
filterBody, | ||
typeof(T), | ||
typeof(TResult), | ||
parameterName | ||
), | ||
opts => opts.Items["parameters"] = GetParameters() | ||
).Build(); | ||
} | ||
|
||
private static TResult RunExpression<T, TResult>(Expression<Func<T, TResult>> filter, T instance) | ||
=> filter.Compile().Invoke(instance); | ||
|
||
private static void AssertExpressionStringIsCorrect(Expression expression, string expected) | ||
{ | ||
AssertStringIsCorrect(ExpressionStringBuilder.ToString(expression)); | ||
|
||
void AssertStringIsCorrect(string resultExpression) | ||
=> Assert.True | ||
( | ||
expected == resultExpression, | ||
$"Expected expression '{expected}' but the deserializer produced '{resultExpression}'" | ||
); | ||
} | ||
} | ||
} |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
18 changes: 18 additions & 0 deletions
18
LogicBuilder.Structures/ExpressionDescriptors/ExceptDescriptor.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
namespace LogicBuilder.Expressions.Utils.ExpressionDescriptors | ||
{ | ||
public class ExceptDescriptor : IExpressionDescriptor | ||
{ | ||
public ExceptDescriptor() | ||
{ | ||
} | ||
|
||
public ExceptDescriptor(IExpressionDescriptor left, IExpressionDescriptor right) | ||
{ | ||
Left = left; | ||
Right = right; | ||
} | ||
|
||
public IExpressionDescriptor Left { get; set; } | ||
public IExpressionDescriptor Right { get; set; } | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
LogicBuilder.Structures/ExpressionDescriptors/UnionDescriptor.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
namespace LogicBuilder.Expressions.Utils.ExpressionDescriptors | ||
{ | ||
public class UnionDescriptor : IExpressionDescriptor | ||
{ | ||
public UnionDescriptor() | ||
{ | ||
} | ||
|
||
public UnionDescriptor(IExpressionDescriptor left, IExpressionDescriptor right) | ||
{ | ||
Left = left; | ||
Right = right; | ||
} | ||
|
||
public IExpressionDescriptor Left { get; set; } | ||
public IExpressionDescriptor Right { get; set; } | ||
} | ||
} |
This file contains 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