Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从验证函数返回额外信息的最佳实践_C# - Fatal编程技术网

C# 从验证函数返回额外信息的最佳实践

C# 从验证函数返回额外信息的最佳实践,c#,C#,我有一个班的员工。我希望在保存之前能够验证()它,以确保所有字段都已填充有效值。 类的用户可以在调用Save()之前调用Validate(),也可以直接调用Save(),然后Save()将调用Validate(),如果验证失败,可能会引发异常 现在,我(主要)的问题是: 如果我的Validate()函数返回一个简单的bool,那么我该如何告诉类的用户出了什么问题,即“Email not filled”、“ID not unique”等。为此,我只想将错误字符串传递给人类用户,但如果我想要一个错误

我有一个班的员工。我希望在保存之前能够验证()它,以确保所有字段都已填充有效值。 类的用户可以在调用Save()之前调用Validate(),也可以直接调用Save(),然后Save()将调用Validate(),如果验证失败,可能会引发异常

现在,我(主要)的问题是:
如果我的Validate()函数返回一个简单的bool,那么我该如何告诉类的用户出了什么问题,即“Email not filled”、“ID not unique”等。为此,我只想将错误字符串传递给人类用户,但如果我想要一个错误代码列表,原理是一样的(除了使位图的使用更具逻辑性之外)

  • 我可以在验证函数中使用Out参数,但我知道这是不可取的
  • 我可以从函数中返回一个字符串数组,然后测试它是否为空(这意味着没有错误),而不是返回bool,但这看起来很混乱,也不正确
  • 我可以创建一个结构来从这个方法返回,包括一个bool和一个带有错误消息的字符串数组,但是看起来很笨拙
  • 我可以返回一个错误代码位图而不是bool并查找它,但这似乎太过分了
  • 我可以在包含错误的对象上创建一个公共属性“ValidationErrors”。但是,这需要我在读取之前调用Validate(),或者从属性()显式调用Validate,这有点浪费
我的具体课程是C#,但这看起来像是一个相当普遍的“最佳实践”问题,我相信我应该知道答案。感谢您的建议

我可以创建一个结构来从这个方法返回,包括一个bool和一个带有错误消息的字符串数组,但是看起来很笨拙

为什么看起来很笨重?创建一个合适的类型来封装信息是完美的。不过我不一定要用字符串来编码这样的信息。枚举可能更合适

另一种方法是对返回类型进行子类化,并为每种情况提供一个额外的子类(如果合适的话)。如果可能发出多个故障信号,则可以使用数组。但我也会将其封装在自己的类型中

一般模式可能如下所示:

class ValidationInfo {
    public bool Valid { get; private set; }
    public IEnumerable<Failure> Failures { get; private set; }
}
类验证信息{
公共布尔有效{get;private set;}
公共IEnumerable失败{get;private set;}
}

我将遵循TryParse方法的模式,并使用具有此签名的方法:

public bool TryValidate(out IEnumerable<string> errors) { ... }
public bool TryValidate(out IEnumerable errors){…}
另一种选择是将验证代码从对象中提取到它自己的类中,可能是基于规范模式构建的

public class EmployeeValidator
{
    public bool IsSatisfiedBy(Employee candidate) 
    { 
        //validate and populate Errors 
    }
    public IEnumerable<string> Errors { get; private set; }
}
公共类EmployeeValidator
{
公共学校(员工候选人)满意
{ 
//验证并填充错误
}
公共IEnumerable错误{get;private set;}
}

我可能会选择位图选项。只需

[Flags]
public enum ValidationError {
    None = 0,
    SomeError = 1,
    OtherError = 2,
    ThirdError = 4
}
…在调用代码中,只需执行以下操作:

ValidationError errCode = employee.Validate();
if(errCode != ValidationError.None) {
    // Do something
}

对我来说似乎很好而且很紧凑。

我们正在使用spring验证和Windows窗体错误提供程序

因此,我们的验证函数返回一个带有控件id和错误消息的字典(对于每个验证错误)。错误提供程序在导致错误的控件附近的弹出字段中显示错误消息


我过去使用过一些其他的验证方案,但这一个效果非常好。

我发现简单地使用一个方法(或者一个属性,因为C#对此有很好的支持)是一个很好的方法,它以某种合理的、易于使用的格式返回所有验证错误消息,比如字符串列表


通过这种方式,您还可以保持validate方法返回bools。

听起来您需要一个泛型类:

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
}
公共密封类验证结果
{
private readonly bool _valid;//可以执行枚举{无效,警告,有效}
私有只读T_结果;
私有只读列表消息;
公共验证结果(T result){{u valid=true;_result=result;_messages=/*空列表*/}
公共静态验证结果错误(IEnumerable消息)
{
_有效=错误;
_结果=默认值(T);
_messages=messages.ToList();
}
公共bool是有效的{get{return\u valid;}}
公共T结果{get{if(!\u valid)抛出新的InvalidOperationException();返回_Result;}
公共IEnumerable消息{get{return\u Messages;}}}//或ReadOnlyCollection可能是更好的返回类型
//理想事物:T的隐式转换
//接受params ValidationMessage[]的错误工厂方法的重载
//你还想要什么
//DataContract,可序列化的属性,使其通过连接
}

您可以看一看Rockford Lhotka的CSLA,其中包含针对R业务对象的广泛业务规则/验证跟踪


www.lhotka.net

我同意Chris W.在阅读Rocky的专家C#Business Objects之前,我问了同样的问题

他有一种处理业务验证规则的绝妙方法。验证是在设置每个属性之后进行的。每当规则被破坏时,对象的状态就会变得无效

您的业务类可以实现IDataError接口。将UI控件绑定到您的业务对象属性将通知您的ErrorProvider控件对象上的任何损坏规则


我真的建议您花点时间看看验证部分。

我只想添加一个对失败内容的引用,如果失败的是属性级规则,则引用该属性,如果是实体范围,则引用实体等。您是对的,我应该对错误消息进行结构化,并有一个中心reposi我可以在哪里找到他们