IDataErrorInfo的实现,过度使用if语句
本文关键字:if 语句 实现 IDataErrorInfo | 更新日期: 2023-09-27 17:54:35
我真的想不出一个更好的方式来形容我的标题,这可能是对我刚刚所做的最准确的描述。这个问题混合了最佳实践和编码风格。
我基本上有一个WPF应用程序,它使用MVVMLight库和实体框架(6.x)与数据库第一工作流。
从数据库生成的一个POCO类大约有44列,请记住这一点。
用于验证此特定对象。我正在使用实现IDataErrorInfo的部分类扩展POCO对象的功能,如下所示:
public partial class MyClass : IDataErrorInfo { ... }
现在这是可以的,直到你记住这个对象有44个字段。这将给我一个索引器它将有180多行if语句
这对我来说就是糟糕的编程实践。这个索引器的结构是这样的:
public string this[string columnName]
{
get
{
switch (columnName)
{
case "Column1":
if (string.IsNullOrWhiteSpace(Column1))
return "A value for Column1 is required.";
// More if-statements here...
break;
case "Column2":
// Same as above.
break;
// There's going to be about another 42 cases here...
}
return null;
}
}
我考虑过的其他事情是将if语句分解成单独的方法,这将减少索引器中的行数,但会引入40多个具有相同结构的方法。
// In the indexer.
switch(columnName)
{
case "Column1":
return ValidateColumn1();
break;
case "Column2":
return ValidateColumn2();
break;
}
// Somewhere a bit further down the class...
private string ValidateColumn1()
{
if (string.IsNullOrWhiteSpace(Column1))
return "A value for Column1 is required.";
// More if-statements...
}
private string ValidateColumn2()
{
// Ditto.
}
我可以理解,有很多方法可以在WPF/EF中进行验证,例如:
- IDataErrorInfo接口
- 好友/元数据类 数据注释
- 绑定验证
,但我只是好奇最好的方法是什么,因为一个200多行的索引器和创建40多个方法/类似乎是一个非常错误的方式去做事情。
我知道我可能在这里问了很多问题,但这是我想要理解的:
- 使用这个问题中的第一个代码片段作为示例,使用if语句验证索引器中POCO对象中的每个列是否被认为是良好的实践?对于一个有5列的对象来说,这似乎还可以,但是对于44列的对象来说,它就变得笨拙了,而且是维护的噩梦。(即使这可能是数据库中的正常化问题)
- 实现验证的最佳/首选方式是什么,还是取决于程序员的需求?
- 是否有其他方法可以解决验证我的POCO对象?我已经看过了FluentValidation库,但是这样做弊大于利,因为我似乎把所有这些不同的库放在一起,希望它们能很好地发挥作用,而它们似乎从来没有这样做过。
这是一种方法(我通常这样做)。我使用EF数据注释(在我的例子中,我用EF数据注释和EF关系流畅接口映射每个实体)。我通常从EntityBase继承标准IDataErrorInfo。这是我的EntityBase
public class EntityBase : IDataErrorInfo
{
public virtual bool IsValid()
{
return GetValidationErrors() == string.Empty;
}
protected virtual string GetValidationErrors()
{
var vc = new ValidationContext(this, null, null);
var vResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(this, vc, vResults, true))
return vResults.Aggregate("", (current, ve) => current + (ve.ErrorMessage + Environment.NewLine));
return "";
}
protected virtual string GetValidationErrors(string columnName)
{
var vc = new ValidationContext(this, null, null);
var vResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(this, vc, vResults, true))
{
string error = "";
foreach (var ve in vResults)
{
if (ve.MemberNames.Contains(columnName, StringComparer.CurrentCultureIgnoreCase))
error += ve.ErrorMessage + Environment.NewLine;
}
return error;
}
return "";
}
string IDataErrorInfo.Error
{
get { return GetValidationErrors(); }
}
string IDataErrorInfo.this[string columnName]
{
get { return GetValidationErrors(columnName); }
}
}
有些实体需要复杂的属性验证(即交叉属性验证)。在本例中,我重写了虚拟方法,并为实体