В моем приложении у меня множество форм, большинство из которых имеют собственные модели, к которым они привязаны! Конечно, валидация данных важна, но разве нет лучшего решения, кроме реализации IDataErrorInfo для всех ваших моделей, а затем написания кода для всех свойств для их проверки?
Я создал помощники проверки, которые удаляют много фактического кода проверки, но все же я не могу не чувствовать, что мне не хватает трюка или два! Могу ли я добавить, что это первое приложение, которое я использовал MVVM внутри, поэтому я уверен, что мне очень нужно учиться на эту тему!
ИЗМЕНИТЬ:
Это код из типичной модели, которая мне действительно не нравится (позвольте мне объяснить):
string IDataErrorInfo.Error
{
get
{
return null;
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
return GetValidationError(propertyName);
}
}
#endregion
#region Validation
string GetValidationError(String propertyName)
{
string error = null;
switch (propertyName)
{
case "carer_title":
error = ValidateCarerTitle();
break;
case "carer_forenames":
error = ValidateCarerForenames();
break;
case "carer_surname":
error = ValidateCarerSurname();
break;
case "carer_mobile_phone":
error = ValidateCarerMobile();
break;
case "carer_email":
error = ValidateCarerEmail();
break;
case "partner_title":
error = ValidatePartnerTitle();
break;
case "partner_forenames":
error = ValidatePartnerForenames();
break;
case "partner_surname":
error = ValidatePartnerSurname();
break;
case "partner_mobile_phone":
error = ValidatePartnerMobile();
break;
case "partner_email":
error = ValidatePartnerEmail();
break;
}
return error;
}
private string ValidateCarerTitle()
{
if (String.IsNullOrEmpty(carer_title))
{
return "Please enter the carer title";
}
else
{
if (!ValidationHelpers.isLettersOnly(carer_title))
return "Only letters are valid";
}
return null;
}
private string ValidateCarerForenames()
{
if (String.IsNullOrEmpty(carer_forenames))
{
return "Please enter the carer forename(s)";
}
else
{
if (!ValidationHelpers.isLettersSpacesHyphensOnly(carer_forenames))
return "Only letters, spaces and dashes are valid";
}
return null;
}
private string ValidateCarerSurname()
{
if (String.IsNullOrEmpty(carer_surname))
{
return "Please enter the carer surname";
}
else
{
if (!ValidationHelpers.isLettersSpacesHyphensOnly(carer_surname))
return "Only letters, spaces and dashes are valid";
}
return null;
}
private string ValidateCarerMobile()
{
if (String.IsNullOrEmpty(carer_mobile_phone))
{
return "Please enter a valid mobile number";
}
else
{
if (!ValidationHelpers.isNumericWithSpaces(carer_mobile_phone))
return "Only numbers and spaces are valid";
}
return null;
}
private string ValidateCarerEmail()
{
if (String.IsNullOrWhiteSpace(carer_email))
{
return "Please enter a valid email address";
}
else
{
if (!ValidationHelpers.isEmailAddress(carer_email))
return "The email address entered is not valid";
}
return null;
}
private string ValidatePartnerTitle()
{
if (String.IsNullOrEmpty(partner_title))
{
return "Please enter the partner title";
}
else
{
if (!ValidationHelpers.isLettersOnly(partner_title))
return "Only letters are valid";
}
return null;
}
private string ValidatePartnerForenames()
{
if (String.IsNullOrEmpty(partner_forenames))
{
return "Please enter the partner forename(s)";
}
else
{
if (!ValidationHelpers.isLettersSpacesHyphensOnly(partner_forenames))
return "Only letters, spaces and dashes are valid";
}
return null;
}
private string ValidatePartnerSurname()
{
if (String.IsNullOrEmpty(partner_surname))
{
return "Please enter the partner surname";
}
else
{
if (!ValidationHelpers.isLettersSpacesHyphensOnly(partner_surname))
return "Only letters, spaces and dashes are valid";
}
return null;
}
private string ValidatePartnerMobile()
{
if (String.IsNullOrEmpty(partner_mobile_phone))
{
return "Please enter a valid mobile number";
}
else
{
if (!ValidationHelpers.isNumericWithSpaces(partner_mobile_phone))
return "Only numbers and spaces are valid";
}
return null;
}
private string ValidatePartnerEmail()
{
if (String.IsNullOrWhiteSpace(partner_email))
{
return "Please enter a valid email address";
}
else
{
if (!ValidationHelpers.isEmailAddress(partner_email))
return "The email address entered is not valid";
}
return null;
}
#endregion
Идея иметь оператор switch для определения правильного свойства, а затем писать уникальные функции проверки для каждого свойства просто слишком много (не с точки зрения работы, а с точки зрения количества требуемого кода). Может быть, это изящное решение, но оно просто не похоже на одно!
Примечание. Я буду преобразовывать мои помощники проверки в расширения, как рекомендовано в одном из ответов (спасибо Sheridan)
РЕШЕНИЕ:
Таким образом, после ответа, который я принял, это голые кости того, что я реализовал, чтобы заставить его работать вначале (очевидно, я буду улучшать детали, но я просто хотел, чтобы это началось первым, поскольку у меня было мало опыта использования лямбда выражений или отражений до их реализации).
Класс словаря Validtion (показывающий основные функции):
private Dictionary<string, _propertyValidators> _validators;
private delegate string _propertyValidators(Type valueType, object propertyValue);
public ValidationDictionary()
{
_validators = new Dictionary<string, _propertyValidators>();
}
public void Add<T>(Expression<Func<string>> property, params Func<T, string>[] args)
{
// Acquire the name of the property (which will be used as the key)
string propertyName = ((MemberExpression)(property.Body)).Member.Name;
_propertyValidators propertyValidators = (valueType, propertyValue) =>
{
string error = null;
T value = (T)propertyValue;
for (int i = 0; i < args.Count() && error == null; i++)
{
error = args[i].Invoke(value);
}
return error;
};
_validators.Add(propertyName, propertyValidators);
}
public Delegate GetValidator(string Key)
{
_propertyValidators propertyValidator = null;
_validators.TryGetValue(Key, out propertyValidator);
return propertyValidator;
}
Реализация модели:
public FosterCarerModel()
{
_validationDictionary = new ValidationDictionary();
_validationDictionary.Add<string>( () => carer_title, IsRequired);
}
public string IsRequired(string value)
{
string error = null;
if(!String.IsNullOrEmpty(value))
{
error = "Validation Dictionary Is Working";
}
return error;
}
Реализация IDataErrorInfo (которая является частью реализации модели):
string IDataErrorInfo.this[string propertyName]
{
get
{
Delegate temp = _validationDictionary.GetValidator(propertyName);
if (temp != null)
{
string propertyValue = (string)this.GetType().GetProperty(propertyName).GetValue(this, null);
return (string)temp.DynamicInvoke(typeof(string), propertyValue);
}
return null;
}
}
Игнорируйте мои соглашения о присвоении имен slapdash и в кодировании мест, я просто так рад, что получил эту работу! Особая благодарность nmclean, конечно, но и благодаря всем, кто внес свой вклад в этот вопрос, все ответы были чрезвычайно полезны, но после некоторого рассмотрения я решил пойти с таким подходом!