Skip to content

Commit

Permalink
• Added the new operation NotIn (thanks to @HowardHoulston for that…
Browse files Browse the repository at this point in the history
… - issue #36)

• Fixed issue #37 (exception thrown when using the `In` operator over a nullable property)
  • Loading branch information
dbelmont committed Jan 16, 2019
1 parent 134e0cd commit 1b1eae0
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 8 deletions.
4 changes: 2 additions & 2 deletions ExpressionBuilder.Test/Integration/OperationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ public class OperationTests
{
private readonly List<string> operationsNames = new List<string> {
"Ends with", "Equal to", "Greater than", "Greater than or equals", "Is empty", "Is not empty", "Is not null", "Is not null nor whitespace", "Is null", "Is null or whitespace", "Less than", "Less than or equals",
"Not equal to", "Starts with", "Does not contain", "Between", "Contains", "In"
"Not equal to", "Starts with", "Does not contain", "Between", "Contains", "In", "NotIn"
};

private readonly List<string> operationsNamesptBR = new List<string> {
"entre", "contem", "termina com", "igual", "maior que", "maior que ou igual", "em", "é vazio", "não é vazio", "não é nulo", "não é nulo nem vazio", "é nulo", "é nulo ou vazio", "menor que","menor que ou igual", "diferente",
"começa com", "não contem"
"começa com", "não contem", "não entre"
};

[TestCase("", TestName = "Should load operation description from resource file")]
Expand Down
3 changes: 3 additions & 0 deletions ExpressionBuilder.Test/Resources/Operations.pt-BR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@
<data name="NotEqualTo" xml:space="preserve">
<value>diferente</value>
</data>
<data name="NotIn" xml:space="preserve">
<value>não entre</value>
</data>
<data name="StartsWith" xml:space="preserve">
<value>começa com</value>
</data>
Expand Down
10 changes: 6 additions & 4 deletions ExpressionBuilder.Test/Unit/HelperTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ExpressionBuilder.Exceptions;
using ExpressionBuilder.Exceptions;
using ExpressionBuilder.Helpers;
using ExpressionBuilder.Interfaces;
using ExpressionBuilder.Test.CustomOperations;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ExpressionBuilder.Test.Unit
{
Expand Down Expand Up @@ -33,6 +33,7 @@ public void SupportedOperationsForNumbers(Type numberType)
if (numberType.IsArray)
{
numberOperations.Add("In");
numberOperations.Add("NotIn");
}

var operations = operationHelper.SupportedOperations(numberType);
Expand All @@ -52,6 +53,7 @@ public void SupportedOperationsForText(Type textType)
if (textType.IsArray)
{
textOperations.Add("In");
textOperations.Add("NotIn");
}

var operations = definitions.SupportedOperations(textType);
Expand Down
7 changes: 6 additions & 1 deletion ExpressionBuilder/Builders/FilterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,13 @@ private void CheckPropertyValueMismatch(MemberExpression member, ConstantExpress
var memberType = member.Member.MemberType == MemberTypes.Property ? (member.Member as PropertyInfo).PropertyType : (member.Member as FieldInfo).FieldType;

var constant1Type = GetConstantType(constant1);
var nullableType = constant1Type != null ? Nullable.GetUnderlyingType(constant1Type) : null;

if (constant1.Value != null && memberType != constant1Type)
var constantValueIsNotNull = constant1.Value != null;
var memberAndConstantTypeDoNotMatch = memberType != constant1Type;
var memberAndNullableUnderlyingTypeDoNotMatch = nullableType != null && memberType != nullableType;

if (constantValueIsNotNull && (memberAndConstantTypeDoNotMatch || memberAndNullableUnderlyingTypeDoNotMatch))
{
throw new PropertyValueTypeMismatchException(member.Member.Name, memberType.Name, constant1.Type.Name);
}
Expand Down
1 change: 1 addition & 0 deletions ExpressionBuilder/ExpressionBuilder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
<Compile Include="Operations\IsNull.cs" />
<Compile Include="Operations\In.cs" />
<Compile Include="Operations\EndsWith.cs" />
<Compile Include="Operations\NotIn.cs" />
<Compile Include="Operations\Operation.cs" />
<Compile Include="Operations\StartsWith.cs" />
<Compile Include="Operations\Contains.cs" />
Expand Down
1 change: 0 additions & 1 deletion ExpressionBuilder/Generics/Filter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using ExpressionBuilder.Builders;
using ExpressionBuilder.Common;
using ExpressionBuilder.Helpers;
using ExpressionBuilder.Interfaces;
using System;
using System.Collections.Generic;
Expand Down
31 changes: 31 additions & 0 deletions ExpressionBuilder/Operations/NotIn.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using ExpressionBuilder.Common;
using System;
using System.Collections;
using System.Linq.Expressions;

namespace ExpressionBuilder.Operations
{
/// <summary>
/// Operation representing the inverse of a list "Contains" method call.
/// </summary>
public class NotIn : OperationBase
{
/// <inheritdoc />
public NotIn()
: base("NotIn", 1, TypeGroup.Default | TypeGroup.Boolean | TypeGroup.Date | TypeGroup.Number | TypeGroup.Text, true, true) { }

/// <inheritdoc />
public override Expression GetExpression(MemberExpression member, ConstantExpression constant1, ConstantExpression constant2)
{
if (!(constant1.Value is IList) || !constant1.Value.GetType().IsGenericType)
{
throw new ArgumentException("The 'NotIn' operation only supports lists as parameters.");
}

var type = constant1.Value.GetType();
var inInfo = type.GetMethod("Contains", new[] { type.GetGenericArguments()[0] });
var contains = Expression.Call(constant1, inInfo, member);
return Expression.Not(contains);
}
}
}
5 changes: 5 additions & 0 deletions ExpressionBuilder/Operations/Operation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ static Operation()
/// </summary>
public static IOperation StartsWith { get { return new StartsWith(); } }

/// <summary>
/// Operation representing the inverse of a list "Contains" method call.
/// </summary>
public static IOperation NotIn { get { return new NotIn(); } }

/// <summary>
/// Instantiates an IOperation given its name.
/// </summary>
Expand Down

0 comments on commit 1b1eae0

Please sign in to comment.