【问题标题】:Design for many different updates to an object? [closed]为一个对象设计许多不同的更新? [关闭]
【发布时间】:2017-03-20 14:50:11
【问题描述】:

我陷入了设计问题。 我的问题是我对问题的解决方案不干净。而且代码看起来不太好。

这就是我想做的:

我有一个普通的类,其属性存储值。 类值必须符合某些规则。

这是一个简化的示例: 一个值类:

 class RecivedOrder
 {
     public AgreementId { get; set; }
     public OrderNr { get; set; }
     public Items { get; set; }
     public ProductId { get; set; }
     public ValidProductId { get; set; }         
     public InStock { get; set; }        
     public CustomerId { get; set; }     
     public NameOfCustomer { get; set; }         
     //..and many more properties..
 }

验证/更新是这样完成的:

 foreach (RecivedOrder o in RecivedDocument.Orders)
 {
    RecivedOrder.AgreementId = CheckIfValidAgreementId(o.AgreementId );
    RecivedOrder.ValidProductId = (bool)CheckIfValidProductId(o.ProductId);
    RecivedOrder.InStock = (bool)CheckProductIsInStock(o.ProductId);
    RecivedOrder.NameOfCustomer = GetNameOfCustomer(o.CustomerId);
    // ...and many more checks/validations....

    // The check methodes can do call to database..

 }

我正在寻找的是一个很好的设计模式。 或者更清洁的方式来做到这一点?

最好的问候 弗雷德里克

【问题讨论】:

    标签: c# .net oop design-patterns


    【解决方案1】:

    就个人而言,我喜欢用于验证情况的一种模式是创建一个 ValidationResults 类,并将其作为我的对象上的 Validate 和 Update 函数的返回值。像这样的东西(超级简单的例子):

    public class ValidationResult
    {
      public bool IsValid { get; set; }
      public string Message { get; set; }
    }
    

    然后,我可能只是在我的 ReceivedOrder 类上定义一个 Validate 方法来返回这个类的一个实例:

    public ValidationResult Validate()
    {
      var result = new ValidationResult();
      result.IsValid = true;
    
      if (!CheckIfValidAgreementId(this.AgreementId))
      {
        result.IsValid = false
        result.Message = "Invalid agreement ID";
      }
      else if (!CheckIfValidProductId(this.ProductId))
      {
        result.IsValid = false;
        result.IsValid = "Invalid product ID";
      }
    
      // ... and so on, with other validations
    
      return result;
    }
    

    然后我可能会在对象上创建一个 Update 方法,以确保发生验证,并将结果传回

    public ValidationResult Update()
    {
      var validationResult = this.Validate();
    
      if (validationResult.IsValid)
      {
        // ... your code to actually update the repository goes here
      }
    
      return validationResult;
    }
    

    现在,在其余代码中,您可以对单个对象调用 Update,并检查返回的结果。IsValid 以验证更新是否成功。如果需要更新倍数,可以循环遍历。

    foreach (ReceivedOrder o in RecivedDocument.Orders)
    {
      var result = o.Update();
    
      if (!result.IsValid)
        MessageBox.Show("failed to update order: " + result.Message); // or however you need to handle this
    }
    

    或者,您可以在调用 Update 之前调用 Validate,如果这更适合您的用例

    foreach (ReceivedOrder o in RecivedDocument.Orders)
    {
      var result = o.Validate();
    
      if (!result.IsValid)
        MessageBox.Show("validation failed: " + result.Message);
      else
        o.Update();
    }
    

    【讨论】:

    • 我想我在这里使用你的建议。谢谢!
    【解决方案2】:

    使用私有变量和 get/set 实现完全实现您的属性。然后您可以在 set 方法中进行检查。例如:

    private object _agreementId;
    public object AgreementId 
    { 
        get { return _agreementId; } 
        set 
        { 
            if( !CheckIfValidAgreementId(value)) 
                throw new ArgumentException(); 
            _agreementId = value; 
        } 
    }
    

    【讨论】:

      【解决方案3】:

      我发现在设计对象时定义类的用途很有帮助。例如,这是一个表示数据库实体的对象,还是一个简单地在点之间存储数据的对象(即 DTO),还是一个属性必须遵守某些规则(即模型)的对象,还是其他类似业务对象的东西也有一些行为.

      看来您的可能属于模型类别。除了此处提供的答案,您还可以考虑解决方案,例如

      【讨论】:

      • FluentValidation 库看起来不错。谢谢!
      【解决方案4】:

      您可以对您的应用程序进行如下编码:

      foreach (RecivedOrder o in RecivedDocument.Orders) 
      {
        if (!ReciveOrder.Check()) 
        {
           ... // Display order content on console
               // Then show errors:
           for (int i=0;i<Errors.Count;i++) Console.Writeline(Errors[i]) ;
        } 
      
      class RecivedOrder
       {
         // your properties
         internal List<String> Errors = null ;
      
         internal bool Check()
         {
           Errors = new List<String>() ;
           CheckAgreementId() ;
           CheckProductId() ;
           ... // other checks
           return Errors.Count==0 ;
         }
      
         internal void CheckAgreementId()
         {
           bool IdOk = AgreementId>=0 ;
           ... // more controls on AgreementId
           if (!IdOk) Errors.Add("Invalid AgreementId="+AgreementId) ;   
         }
      
          internal void CheckProductId()
         {
           ... 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-29
        • 2011-12-31
        相关资源
        最近更新 更多