IDataErrorInfo的实现,过度使用if语句

时间:2015-06-09 03:59:11

标签: c# entity-framework validation mvvm-light

我无法想出一个更好的方式来标题我的标题,它可能是我刚才所做的最准确的描述。这个问题是最佳实践和编码风格的混合。

我基本上有一个WPF应用程序,它使用MVVMLight库和Entity Framework(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中进行验证,例如:

但我很好奇最好的方法是什么,因为200多行索引器和创建40多个方法/类似乎是一种非常错误的方法。

我知道我可能会在这里提出多个问题,但这是我试图理解的内容:

  1. 使用this问题中的第一个代码段作为示例,使用if语句验证索引器中POCO对象中的每个列是否为良好做法? 对于一个有5列的对象,这似乎没问题,但是对于44,它变得难以处理并且是维护噩梦。 (尽管这可能是数据库中的规范化问题。)
  2. 实施验证的最佳/首选方式是什么,还是取决于程序员的要求?
  3. 我可以通过其他方式来验证我的POCO对象吗?我查看了FluentValidation库,但这样做弊大于利,因为我似乎把所有这些不同的库放在一起,并希望它们能够很好地协同工作,这似乎是他们从未做过的。
  4. 提前致谢。

1 个答案:

答案 0 :(得分:1)

这是一种方法(我通常这样做)。 我使用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); }
    }

}

有些实体需要复杂的属性验证(即交叉属性验证)。在这种情况下,我覆盖虚拟方法并向实体添加特定验证