: Bir CarriageReturn, hata listesini ayrılmış şöyle ben doesnt yapmak istediğim doğal bulunduğuna bakın düşünüyorum, bu yüzden sadece nesne üzerinde hatalar (güncellenmiş zaman bir özellik değişiklikleri) ait bir sözlük oluşturulur ve hata geri dönelim
Doğrulama niteliklerini kullanmanın çok daha kolay olduğunu düşünüyorum.
class MyBusinessObject {
[Required(ErrorMessage="Must enter customer")]
public string Customer { get; set; }
[Range(10,99, ErrorMessage="Price must be between 10 and 99")]
public decimal Price { get; set; }
// I have also created some custom attributes, e.g. validate paths
[File(FileValidation.IsDirectory, ErrorMessage = "Must enter an importfolder")]
public string ImportFolder { get; set; }
public string this[string columnName] {
return InputValidation<MyBusinessObject>.Validate(this, columnName);
}
public ICollection<string> AllErrors() {
return InputValidation<MyBusinessObject>.Validate(this);
}
}
yardımcı sınıfı InputValidation bu
internal static class InputValidation<T>
where T : IDataErrorInfo
{
/// <summary>
/// Validate a single column in the source
/// </summary>
/// <remarks>
/// Usually called from IErrorDataInfo.this[]</remarks>
/// <param name="source">Instance to validate</param>
/// <param name="columnName">Name of column to validate</param>
/// <returns>Error messages separated by newline or string.Empty if no errors</returns>
public static string Validate(T source, string columnName) {
KeyValuePair<Func<T, object>, ValidationAttribute[]> validators;
if (mAllValidators.TryGetValue(columnName, out validators)) {
var value = validators.Key(source);
var errors = validators.Value.Where(v => !v.IsValid(value)).Select(v => v.ErrorMessage ?? "").ToArray();
return string.Join(Environment.NewLine, errors);
}
return string.Empty;
}
/// <summary>
/// Validate all columns in the source
/// </summary>
/// <param name="source">Instance to validate</param>
/// <returns>List of all error messages. Empty list if no errors</returns>
public static ICollection<string> Validate(T source) {
List<string> messages = new List<string>();
foreach (var validators in mAllValidators.Values) {
var value = validators.Key(source);
messages.AddRange(validators.Value.Where(v => !v.IsValid(value)).Select(v => v.ErrorMessage ?? ""));
}
return messages;
}
/// <summary>
/// Get all validation attributes on a property
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
private static ValidationAttribute[] GetValidations(PropertyInfo property) {
return (ValidationAttribute[])property.GetCustomAttributes(typeof(ValidationAttribute), true);
}
/// <summary>
/// Create a lambda to receive a property value
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
private static Func<T, object> CreateValueGetter(PropertyInfo property) {
var instance = Expression.Parameter(typeof(T), "i");
var cast = Expression.TypeAs(Expression.Property(instance, property), typeof(object));
return (Func<T, object>)Expression.Lambda(cast, instance).Compile();
}
private static readonly Dictionary<string, KeyValuePair<Func<T, object>, ValidationAttribute[]>> mAllValidators;
static InputValidation() {
mAllValidators = new Dictionary<string, KeyValuePair<Func<T, object>, ValidationAttribute[]>>();
foreach (var property in typeof(T).GetProperties()) {
var validations = GetValidations(property);
if (validations.Length > 0)
mAllValidators.Add(property.Name,
new KeyValuePair<Func<T, object>, ValidationAttribute[]>(
CreateValueGetter(property), validations));
}
}
}
Bu güzel. En son hata iletisiyle errorCollection'ı güncel tutmak daha iyi olurdu (eğer anahtar zaten mevcutsa ve mesaj boş değil ise). – danjarvis
'Error' özelliği şu amaç için optimize edilebilir:' get {return string.Join (Environment.NewLine, errorCollection.Values); } ', boşsa, yalnızca" "döndürür; bu, (arabirim belgelerinde yazılıdır) hata olarak kabul edilmez. – Tatranskymedved