Fecha de inicio del Validador NHiberate antes de la fecha de finalización
-
14-11-2019 - |
Pregunta
Usando Nhibernate Validator (con S#harp Architecture/MVC3), ¿cómo puedo escribir un atributo personalizado, preferiblemente no específico de objeto (ya que este es un requisito bastante común) que impone que PropiedadA >= PropiedadB (o en el caso más general, ambos pueden ser nulos).
Algo como
public DateTime? StartDate { get; set; }
[GreaterThanOrEqual("StartDate")]
public DateTime? EndDate { get; set; }
Veo que puedo anular IsValid
en particular Entity
class pero no estaba seguro de si ese era el mejor enfoque y no veía cómo proporcionar un mensaje en ese caso.
Solución
Cuando necesita comparar varias propiedades de un objeto como parte de la validación, necesita un validador de clauss.El atributo se aplica luego a la clase, no a la propiedad.
No creo que haya uno existente para hacer lo que quiera, pero es lo suficientemente fácil de escribir el suyo.
Aquí hay un contorno de código para mostrarle aproximadamente cómo podría parecer su validador
[AttributeUsage(AttributeTargets.Class)]
[ValidatorClass(typeof(ReferencedByValidator))]
public class GreaterThanOrEqualAttribute : EmbeddedRuleArgsAttribute, IRuleArgs
{
public GreaterThanOrEqualAttribute(string firstProperty, string secondProperty)
{
/// Set Properties etc
}
}
public class ReferencedByValidator : IInitializableValidator<GreaterThanOrEqualAttribute>
{
#region IInitializableValidator<ReferencedByAttribute> Members
public void Initialize(GreaterThanOrEqualAttribute parameters)
{
this.firstProperty = parameters.FirstProperty;
this.secondProperty = parameters.SecondProperty;
}
#endregion
#region IValidator Members
public bool IsValid(object value, IConstraintValidatorContext constraintContext)
{
// value is the object you are trying to validate
// some reflection code goes here to compare the two specified properties
}
#endregion
}
}
Otros consejos
Actualmente, si necesito hacer esto en un modelo, tengo el modelo implementado IValidatableObject
public class DateRangeModel : IValidatableObject {
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> results = new List<ValidationResult>();
if (StartDate > EndDate)
{
results.Add(new ValidationResult("The Start Date cannot be before the End Date.", "StartDate"));
}
return results;
}
Esto parece proporcionar una buena integración con el sistema existente.El inconveniente es que, dado que esto no se aplica al objeto de dominio, necesita lógica adicional allí (o en una capa de servicios que crea los objetos de dominio, etc.) para aplicarlo también desde ese extremo, en caso de que se use un modelo diferente en otro lugar. para crear o actualizar los objetos del dominio.