我有一个班级员工。我希望能够在保存之前验证它()以确保所有字段都填充了有效值。 类的用户可以在调用Save()之前调用Validate(),或者他们可以直接调用Save(),然后Save()将调用Validate(),如果验证失败,可能会抛出异常。
现在,我的(主要)问题是这个;
如果我的Validate()函数返回一个简单的bool,那么如何告诉用户该类的错误,即“未填写电子邮件”,“ID不唯一”等。出于此目的,我只想要错误字符串传递给人类用户,但如果我想要一个错误代码列表(除了使位图的使用更符合逻辑),原则是相同的。
我的特定程序是在C#中,但这看起来像是一个相当通用的“最佳实践”问题,我相信我应该知道答案。感谢任何建议。
答案 0 :(得分:6)
我可以创建一个仅用于从此方法返回的Struct,包括bool和带有错误消息的字符串数组,但看起来很笨拙。
为什么看起来很笨重?创建适当的类型来封装信息是完美的。但是,我不一定会使用字符串来编码这些信息。枚举可能更适合。
另一种方法是对返回类型进行子类化,并为每种情况提供额外的子类 - 如果这是合适的话。如果可能发出多个故障信号,则表示阵列正常。但我也会将其封装在一个自己的类型中。
一般模式可能如下所示:
class ValidationInfo {
public bool Valid { get; private set; }
public IEnumerable<Failure> Failures { get; private set; }
}
答案 1 :(得分:5)
我可能会选择bitmap-option。简单
[Flags]
public enum ValidationError {
None = 0,
SomeError = 1,
OtherError = 2,
ThirdError = 4
}
...在调用代码中,只需:
ValidationError errCode = employee.Validate();
if(errCode != ValidationError.None) {
// Do something
}
对我而言似乎很好,也很紧凑。
答案 2 :(得分:2)
听起来你需要一个通用类:
public sealed class ValidationResult<T>
{
private readonly bool _valid; // could do an enum {Invalid, Warning, Valid}
private readonly T _result;
private readonly List<ValidationMessage> _messages;
public ValidationResult(T result) { _valid = true; _result = result; _messages = /* empty list */; }
public static ValidationResult<T> Error(IEnumerable<ValidationMessage> messages)
{
_valid = false;
_result = default(T);
_messages = messages.ToList();
}
public bool IsValid { get { return _valid; } }
public T Result { get { if(!_valid) throw new InvalidOperationException(); return _result; } }
public IEnumerable<ValidationMessage> Messages { get { return _messages; } } // or ReadOnlyCollection<ValidationMessage> might be better return type
// desirable things: implicit conversion from T
// an overload for the Error factory method that takes params ValidationMessage[]
// whatever other goodies you want
// DataContract, Serializable attributes to make this go over the wire
}
答案 3 :(得分:1)
我会遵循TryParse方法的模式并使用带有此签名的方法:
public bool TryValidate(out IEnumerable<string> errors) { ... }
另一种选择是将验证码从对象中拉出到自己的类中,可能建立在规范模式上。
public class EmployeeValidator
{
public bool IsSatisfiedBy(Employee candidate)
{
//validate and populate Errors
}
public IEnumerable<string> Errors { get; private set; }
}
答案 4 :(得分:1)
我发现这是一个很好的方法,只需要一个方法(或一个属性,因为C#有很好的支持),它以某种明智,易于使用的格式返回所有验证错误消息,例如列表字符串。
这样你也可以保持你的验证方法回归bools。
答案 5 :(得分:1)
您可以查看Rockford Lhotka的CSLA,其中包含广泛的业务规则/验证跟踪业务对象。
www.lhotka.net
答案 6 :(得分:1)
我同意Chris W.在阅读Rocky的专家C#Business Objects之前,我问了同样的问题。
他有一种处理业务验证规则的出色方法。在设置每个属性后进行验证。每当规则被破坏时,对象的状态变为InValid。
您的业务类可以实现IDataError接口。将UI控件绑定到业务对象属性后,将通知ErrorProvider控件对象上的任何损坏规则。
我真的建议你花点时间看一下验证部分。
答案 7 :(得分:0)
我们正在使用Spring验证和Windows窗体错误提供程序。
因此,我们的验证函数返回一个带有控件ID和错误消息的字典(对于每个验证错误)。错误提供程序在控件附近的弹出字段中显示错误消息,导致错误。
我过去曾使用过其他一些验证方案 - 但这个方案效果很好。