Soporte de políticas de validación al estilo EntLib VAB o NHibernate Validator Tags

Developer
Jul 18, 2010 at 2:41 PM

Para proveer soporte de múltiples reglas de validación para soportar distintos escenarios en un mismo tipo como se describe en http://vale.codeplex.com/workitem/11 se puede implementar inicialmente de dos maneras, hoy en día funciona así:

 public class Persona
{
    public string Nombre { get; set; }
}


[Test]
public void RuleMatchShouldNotBeValid()
{
    Persona persona = new Persona();
    persona.Nombre = "juan gomez";

    var engine = new AltNetHispano.Vale.Validator();
    engine.Register<Persona>(p=>engine.StringLen("Nombre", p.Nombre,2));

    var results = engine.GetInvalidMessages(persona);

    results.Should().Be.Empty();
}

La idea es poder hacer algo así:

//agrega validaciones para regla1
validator.Register<Person>(p => validator.StringIsRequired("Name", p.Name), "regla1");

//agrega validaciones para regla2
validator.Register<Person>(p => validator.StringLen("Name", p.Name, 10), "regla2");

//ejecuta validaciones para regla1 solamente
var invalidMessages = validator.GetInvalidMessages(person, "regla1");

Se puede implementar como lo hacer EntLib Validation Application Block por medio de Rules, en donde las rules contienen validaciones para cada tipo

public class Persona
{
    [Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator(2,Ruleset= "regla1")]
    [Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator(30, Ruleset = "regla2")]
    public string Nombre { get; set; }
}


[Test]
public void NoRuleMatchShouldBeValid()
{
    Persona persona = new Persona();
    persona.Nombre = "juan gomez";

    var results = Microsoft.Practices.EnterpriseLibrary.Validation.Validation.Validate<Persona>(persona);

    results.IsValid.Should().Be.True();
}

[Test]
public void RuleMatchShouldNotBeValid()
{
    Persona persona = new Persona();
    persona.Nombre = "juan gomez";

    var results = Microsoft.Practices.EnterpriseLibrary.Validation.Validation.Validate<Persona>(persona, "regla1");

    results.IsValid.Should().Be.False();
}

La limitación es que las se definen reglas que contienen tipos con un criterio de validación, en cambio NHibernate Validator soporta el concepto de tag que funciona así

public class Error { }
public class Warning { }
public enum MyEnum { Error, Warining }
public class Entity
{
    [Min(Value = 20, Tags = typeof(Error))]
    [Max(Tags = new[] { typeof(Error), typeof(Warning) }, Value = 100)]
    public int ValueUsingTypes { get; set; }
    [Min(Value = 20, Tags = "error")]
    [Max(Tags = new[] { "error", "warning" }, Value = 100)]
    public int ValueUsingStrings { get; set; }
    [Min(Value = 20, Tags = MyEnum.Error)]
    [Max(Tags = new[] { MyEnum.Error, MyEnum.Warining }, Value = 100)]
    public int ValueUsingEnums { get; set; }
    [Min(20)]
    [Max(100)]
    public int ValueWithoutTags { get; set; }
}

//validación 1
var entity = new Entity();validatorEngine.Validate(entity);

//validación 2
var entity = new Entity();
validatorEngine.Validate(entity, typeof(Error), MyEnum.Error, "error");

Según explica Fabio en su blog

http://fabiomaulo.blogspot.com/2009/11/nhibernatevalidator-tags.html

Cómo deberiamos implementarlo en Vale? personalmente creo que la segunda opción (NHV) es más potente sin embargo es más compleja también, yo he utilizado mucho VAB y no recuerdo escenarios donde la limitación de las Rules haya sido un problema.