IDataErrorInfo 的实现,过度使用 if-statements
Implementation of IDataErrorInfo, excessive use of if-statements
我真的想不出更好的方式来表达我的标题,这可能是对我刚刚所做的事情最准确的描述。这个问题结合了最佳实践和编码风格。
我基本上已经有了一个 WPF 应用程序,它使用 MVVMLight 库和 Entity Framework (6.x) 以及数据库优先工作流。
从数据库生成的一个 POCO classes 大约有 44 列,请暂时记住这一点。
用于验证此特定 object。我正在使用实现 IDataErrorInfo 的部分 class 扩展 POCO object 的功能,如下所示:
public partial class MyClass : IDataErrorInfo { ... }
现在可以了,直到您记得这个 object 有 44 个字段。这将给我一个索引器,该索引器将包含 180 多行 if-statements.
这对我来说简直就是糟糕的编程习惯。这个索引器的结构如下所示:
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 接口
- Buddy/Metadata classes
- 数据注释
- Binding Validation
但我很好奇解决这个问题的最佳方法是什么,因为 200 多行索引器和创建 40 多行 methods/classes 似乎是一种非常错误的处理方式。
我知道我可能在这里问了多个问题,但这是我想了解的:
- 以 this 问题中的第一个代码片段为例,使用 if-statements 验证索引器中 POCO object 中的每一列是否被认为是好的做法?
对于具有 5 列的 object,这似乎没问题,但是对于 44 列,它变得笨拙并且是维护的噩梦。 (尽管这可能是数据库中的规范化问题。)
- 实现验证的best/preferred方法是什么,还是取决于程序员的要求?
- 有没有其他方法可以验证我的 POCO objects?我查看了 FluentValidation 库,但这弊大于利,因为我似乎将所有这些不同的库放在一起并希望它们能很好地协同工作,但它们似乎从来没有这样做过。
提前致谢。
这是一种方法(我通常这样做)。
我使用 EF 数据注释(在我的例子中,我使用 EF 数据注释和 EF 流畅的关系接口映射每个实体)。
我通常从具有标准 IDataErrorInfo 的 EntityBase 继承。
这是我的 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); }
}
}
有些实体需要复杂的 属性 验证(即交叉 属性 验证)。在这种情况下,我重写了虚拟方法并向实体添加了特定的验证
我真的想不出更好的方式来表达我的标题,这可能是对我刚刚所做的事情最准确的描述。这个问题结合了最佳实践和编码风格。
我基本上已经有了一个 WPF 应用程序,它使用 MVVMLight 库和 Entity Framework (6.x) 以及数据库优先工作流。
从数据库生成的一个 POCO classes 大约有 44 列,请暂时记住这一点。
用于验证此特定 object。我正在使用实现 IDataErrorInfo 的部分 class 扩展 POCO object 的功能,如下所示:
public partial class MyClass : IDataErrorInfo { ... }
现在可以了,直到您记得这个 object 有 44 个字段。这将给我一个索引器,该索引器将包含 180 多行 if-statements.
这对我来说简直就是糟糕的编程习惯。这个索引器的结构如下所示:
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 接口
- Buddy/Metadata classes
- 数据注释
- Binding Validation
但我很好奇解决这个问题的最佳方法是什么,因为 200 多行索引器和创建 40 多行 methods/classes 似乎是一种非常错误的处理方式。
我知道我可能在这里问了多个问题,但这是我想了解的:
- 以 this 问题中的第一个代码片段为例,使用 if-statements 验证索引器中 POCO object 中的每一列是否被认为是好的做法? 对于具有 5 列的 object,这似乎没问题,但是对于 44 列,它变得笨拙并且是维护的噩梦。 (尽管这可能是数据库中的规范化问题。)
- 实现验证的best/preferred方法是什么,还是取决于程序员的要求?
- 有没有其他方法可以验证我的 POCO objects?我查看了 FluentValidation 库,但这弊大于利,因为我似乎将所有这些不同的库放在一起并希望它们能很好地协同工作,但它们似乎从来没有这样做过。
提前致谢。
这是一种方法(我通常这样做)。 我使用 EF 数据注释(在我的例子中,我使用 EF 数据注释和 EF 流畅的关系接口映射每个实体)。 我通常从具有标准 IDataErrorInfo 的 EntityBase 继承。 这是我的 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); }
}
}
有些实体需要复杂的 属性 验证(即交叉 属性 验证)。在这种情况下,我重写了虚拟方法并向实体添加了特定的验证