需要一个良好的架构来验证规则

时间:2013-05-21 13:46:02

标签: c# validation

我希望你们能给我一些好的建议。我在想如何为C#开发建立一个好的架构。我正在尽力解释情景,因为我不擅长英语:

1)两个班级:Blue Bank和Red Bank

2)第三课:验证规则

3)蓝色和红色银行有几个字段(值),如AccountNumber,Amount,InvoicePeriod等......示例(xml):

Blue Bank

  <AccountNumber>Maria 5987593457</AccountNumber>
  <Amount>200.00</Amount>
  <InvoicePeriod>1</InvoicePeriod>

Red Bank

  <AccountNumber>8529458</AccountNumber>
  <Amount>300.00</Amount>
  <InvoicePeriod>0</InvoicePeriod>

红色/蓝色银行有一些相同的验证规则,例如必须是数字的金额字段。但Red / Blue Banks有不同的验证规则 - AccountNumber字段必须是Blue Bank的字母数字,而AccountNumber必须是Red Bank中的数字,否则将失败。 InvoicePeriod字段在Red Bank中必须为默认值1,而在Blue Bank中必须为默认值0,否则将失败。

我的想法是:

我想为不同的验证规则创建每个Red / Blue Bank类,然后我还为Blue / Red银行的相同规则创建验证类规则。

我的代码在这里:

蓝银班:

  • 验证必须为alphanumberic的AccountNumber,否则失败
  • 验证InvoicePeriod必须是默认值1否则失败

红银班:

  • 验证必须是数字的帐号,否则失败
  • 验证InvoicePeriod必须为默认值0否则失败

RulesOfValidation类

  • 验证必须是数字的金额(红色/蓝色银行类的规则相同)

如何使用dictonary&lt;,&gt;这些课程?或者您的示例代码有什么更好的建议吗?

我们非常感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

Specification Pattern是您的问题的一个很好的选择。您可以为每个特定需求创建公共银行规则和其他规范类的规范类。

此模式有一些c#库:

答案 1 :(得分:1)

我会使用IRule接口使用Validate()方法,该方法可以在包含验证逻辑的具体验证类中实现。然后,您将能够在银行中执行多个自定义规则。将IRule类型对象列表传递给银行类,并在每个传递的银行参数上运行Validate()。因此,每家银行都可以根据通过的规则进行验证。

interface IRule
{
    bool Validate(Bank someBank);
}

abstract class Bank
{
    public string AccountNumber;
    public string Amount;
    public string InvoicePeriod;

    private List<IRule> listOfRules = new List<IRule>();

    public void ValidateAllRules(){
        foreach (var ite in listOfRules){
            ite.Validate(this);
            //if validation will not pass then I don't know what you want to do ;)
        }
    }

    public void AddRule(IRule rule)
    {
        listOfRules.Add(rule);
    }
}

class RedBank : Bank
{
    public RedBank(){
        listOfRules.Add(new SimpleRule());
        listOfRules.Add(new SimpleRule2());
    }
}

class SimpleRule : IRule
{
    public bool Validate(Bank someBank)
    {
        return someBank.AccountNumber.Contains("567");
    }
}

class SimpleRule2 : IRule
{
    public bool Validate(Bank someBank)
    {
        return someBank.Amount.Contains(".") && someBank.InvoicePeriod.Contains("-");
    }
}

答案 2 :(得分:0)

您应该使用System.ComponentModel.DataAnnotations

首先创建抽象类Bank

abstract class Bank
{
    #region fields
    private List<string> errorMessages = new List<string>();
    #endregion

    #region publioc methods
    public virtual void Validate()
    {
        ValidateRulesAtributes();
    }

    #endregion

    #region helper methods
    private void ValidateRulesAtributes()
    {
        var validationContext = new ValidationContext(this, null, null); //ValidationContext -> Reference System.ComponentModel.DataAnnotations
        var result = new List<ValidationResult>();
        Validator.TryValidateObject(this, validationContext, result, true);



        result.ForEach(p => { errorMessages.Add(p.ErrorMessage); });

        if (errorMessages.Any())
            throw new Exception(errorMessages.Aggregate((m1, m2) => String.Concat(m1, Environment.NewLine, m2)));
    }

    protected void Validate(List<string> messages)
    {
        if (errorMessages == null)
            errorMessages = new List<string>();

        if (messages != null)
            messages.ForEach(p => { errorMessages.Add(p); });
        ValidateRulesAtributes();

    }
    #endregion
    #region properties
    //Abstract to indicate Validation atributes 

    public abstract string AccountNumber { get; set; }

    public abstract double Amount { get; set; }
    public abstract int InvoicePeriod { get; set; }
    #endregion

}

使用数据分配创建红色和蓝色银行

class BlueBank : Bank
    {
        //All is ok, no validate 
        public override string AccountNumber { get; set; }

        public override double Amount { get; set; }

        public override int InvoicePeriod { get; set; }

    }
class RedBank : Bank
    {
        [Required()]
        public override string AccountNumber { get; set; }

        public override double Amount { get; set; }
        [Range(0,0)]
        public override int InvoicePeriod { get; set; }


        public override void Validate()
        {
            List<string> errors=new List<string>();
            if (AccountNumber != "Test")
                errors.Add("Worng Account");
            base.Validate(errors);
        }

    }

使用Atributes验证范围,必需等。 将Validate()覆盖为复杂验证

这是一个简单的例子

class Program
    {
        static void Main(string[] args)
        {
            RedBank red = new RedBank();
            red.AccountNumber = "Test";

            red.Amount=0;
            red.Validate(); //this No fail

            red.InvoicePeriod = 3; //This Fail;
            red.Validate(); 

            red.AccountNumber = "PD";
            red.Validate(); //this fal:

        }
    }