gpt4 book ai didi

c# - MVVM - 验证真的需要这么麻烦吗?

转载 作者:可可西里 更新时间:2023-11-01 08:20:57 25 4
gpt4 key购买 nike

在我的应用程序中,我有大量的表单,其中大部分都有自己的绑定(bind)模型!当然数据验证很重要,但是没有比为所有模型实现 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's 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's 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's 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's 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's 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's 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)

解决方案:

所以,按照我接受的答案,这是我为让它最初工作而实现的基本框架(显然我会改进部分 - 但我只是想先让它开始,因为我没有使用 lambda 的经验实现之前的表达或反射(reflection))。

Validtion Dictionary 类(显示主要功能):

    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;
}
}

忽略我草率的命名约定和地方编码,我很高兴能让它工作!当然要特别感谢 nmclean,还要感谢为这个问题做出贡献的每个人,所有回复都非常有帮助,但经过一番考虑后我决定采用这种方法!

最佳答案

我使用 extension 方法来减少我必须编写的验证文本的数量。如果您不熟悉它们,请查看 Extension Methods (C# Programming Guide) MSDN 上的页面以了解有关 extension 方法的信息。我有几十个这样的验证每一种情况。例如:

if (propertyName == "Title" && !Title.ValidateMaximumLength(255)) error = 
propertyName.GetMaximumLengthError(255);

Validation.cs 类中:

public static bool ValidateMaximumLength(this string input, int characterCount)
{
return input.IsNullOrEmpty() ? true : input.Length <= characterCount;
}

public static string GetMaximumLengthError(this string input, int characterCount,
bool isInputAdjusted)
{
if (isInputAdjusted) return input.GetMaximumLengthError(characterCount);
string error = "The {0} field requires a value with a maximum of {1} in it.";
return string.Format(error, input, characterCount.Pluralize("character"));
}

请注意,Pluralize 是另一种扩展 方法,如果输入值不等于 1,它会在输入参数的末尾简单地添加一个“s”。另一种方法可能是:

public static bool ValidateValueBetween(this int input, int minimumValue, int 
maximumValue)
{
return input >= minimumValue && input <= maximumValue;
}

public static string GetValueBetweenError(this string input, int minimumValue, int
maximumValue)
{
string error = "The {0} field value must be between {1} and {2}.";
return string.Format(error, input.ToSpacedString().ToLower(), minimumValue,
maximumValue);
}

当然,实现您需要的所有方法需要一些时间,但之后您将节省大量时间,并且您将获得所有错误消息保持一致的额外好处。

关于c# - MVVM - 验证真的需要这么麻烦吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18869235/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com