secret
Created

FluentValidation for generic unique values

  • Download Gist
Error.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Test Name: Nao_deve_permitir_nome_duplicados
Test FullName: Project.Test.FluentValidation.ModalidadeValidatorTest.Nao_deve_permitir_nome_duplicados
Test Source: {path}\Project.Test\FluentValidation\ModalidadeValidatorTest.cs : line 28
Test Outcome: Failed
Test Duration: 0:00:00,4946356
 
Result Message:
Test method Project.Test.FluentValidation.ModalidadeValidatorTest.Nao_deve_permitir_nome_duplicados threw exception:
System.ArgumentException: Expression of type 'System.Func`2[Project.Model.Modalidade,System.Int32]' cannot be used for return type 'System.Int32'
Result StackTrace:
at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, Boolean tailCall, IEnumerable`1 parameters)
at Project.Web.Validacoes.UniqueValidator`1.IsValid(PropertyValidatorContext context) in {path}\Validacoes\UniqueValidator.cs:line 39
at FluentValidation.Validators.PropertyValidator.Validate(PropertyValidatorContext context) in {path}\PropertyValidator.cs:line 63
at FluentValidation.Internal.PropertyRule.<Validate>d__c.MoveNext() in {path}\Internal\PropertyRule.cs:line 216
at System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at FluentValidation.AbstractValidator`1.Validate(ValidationContext`1 context) in {path}\AbstractValidator.cs:line 83
at FluentValidation.TestHelper.ValidatorTester`2.ValidateError(T instanceToValidate) in {path}\ValidatorTester.cs:line 46
at Project.Test.FluentValidation.ModalidadeValidatorTest.Nao_deve_permitir_nome_duplicados() in {path}\ModalidadeValidatorTest.cs:line 36
RuleBuilderExtensions.cs
C#
1 2 3 4 5 6 7 8
public static IRuleBuilderOptions<T, TElement> MustBeUnique<T, TElement, TEntity>(this IRuleBuilder<T, TElement> ruleBuilder
, Expression<Func<TEntity, int>> propertyId
, IRepository<TEntity> repository
)
where TEntity : class, IEntity
{
return ruleBuilder.SetValidator(new UniqueValidator<TEntity>(propertyId, repository));
}
UniqueValidator.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
public class UniqueValidator<T> : PropertyValidator
where T : class, IEntity
{
private readonly Expression<Func<T, int>> PropertyId;
private readonly IRepository<T> Repository;
 
public UniqueValidator(Expression<Func<T, int>> propertyId, IRepository<T> repository)
: base("{PropertyName} já existe!")
{
PropertyId = propertyId;
Repository = repository;
}
 
protected override bool IsValid(PropertyValidatorContext context)
{
// TODO: Not Work!!
// Read: https://fluentvalidation.codeplex.com/discussions/353331#post1050039 and http://stackoverflow.com/questions/16765086/dynamic-expression-for-filter-iqueryable
 
if (context.PropertyValue == null || string.IsNullOrWhiteSpace(context.PropertyValue.ToString()))
return true;
 
var currentId = Expression.Lambda<Func<int>>(PropertyId).Compile()(); // ERROR HERE
 
// From: http://msdn.microsoft.com/en-us/library/vstudio/bb882637.aspx, http://msdn.microsoft.com/en-us/library/bb397951.aspx
// Compose the expression tree that represents the parameter to the predicate.
 
// p => p.Id != currentId
ParameterExpression pId = Expression.Parameter(typeof(int), "Id");
ConstantExpression cId = Expression.Constant(currentId, typeof(int));
BinaryExpression notCurrent = Expression.NotEqual(pId, cId);
Expression<Func<int, bool>> NotCurrentExpr =
Expression.Lambda<Func<int, bool>>(
notCurrent,
new ParameterExpression[] { pId });
// p.{PropertyName} == context.PropertyValue
ParameterExpression pUnique = Expression.Parameter(typeof(string), context.PropertyName);
ConstantExpression cUnique = Expression.Constant(context.PropertyValue, typeof(string));
BinaryExpression checkUnique = Expression.Equal(pId, cId);
Expression<Func<string, bool>> CheckUniqueExp =
Expression.Lambda<Func<string, bool>>(
checkUnique,
new ParameterExpression[] { pUnique });
 
var exp = Expression.And(NotCurrentExpr, CheckUniqueExp);
 
throw new NotImplementedException();
 
/*
if (currentId > 0)
return Repository.All().Provider.CreateQuery(exp); // y(p => p.Id != currentId && p.{HowToGetPropertyByExpression?} == context.PropertyValue)
return Repository.All().Any(checkUnique);
*/
}
}
XXValidator.cs
C#
1 2 3 4 5 6 7 8 9
public class ModalidadeValidator : AbstractValidator<ModalidadeViewModel>
{
public ModalidadeValidator(IXXRepository repositorio)
{
RuleFor(p => p.Name)
.MustBeValidName()
.MustBeUnique(p => p.Id, repositorio);
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.