Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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#_.net_Oop_Design Patterns - Fatal编程技术网

C# 为一个对象设计许多不同的更新?

C# 为一个对象设计许多不同的更新?,c#,.net,oop,design-patterns,C#,.net,Oop,Design Patterns,我陷入了一个设计问题。 我的问题是我对这个问题的解决方案不干净。代码看起来不太好 这就是我想做的: 我有一个普通类,它的属性存储值。 类值必须根据某些规则进行验证 这是一个简化的示例: 价值类别: class RecivedOrder { public AgreementId { get; set; } public OrderNr { get; set; } public Items { get; set; } public ProductId {

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

这就是我想做的:

我有一个普通类,它的属性存储值。 类值必须根据某些规则进行验证

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

 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..

 }
我要找的是一个很好的设计模式。 还是一种更干净的方法

致意
Fredrik

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

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

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

然后,我可能会在我的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,并检查返回的result.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 yourself,如果这更适合您的用例的话

foreach (ReceivedOrder o in RecivedDocument.Orders)
{
  var result = o.Validate();

  if (!result.IsValid)
    MessageBox.Show("validation failed: " + result.Message);
  else
    o.Update();
}

您可以按以下方式对应用程序进行编码:

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()
   {
     ... 
foreach(RecivedDocument.Orders中的RecivedOrder o)
{
如果(!ReciveOrder.Check())
{
…//在控制台上显示订单内容
//然后显示错误:
对于(int i=0;i=0;
…//有关AgreementId的更多控件
如果(!IdOk)错误。添加(“无效的AgreementId=“+AgreementId”);
}
内部无效检查产品ID()
{
... 

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

你可能会进入模型范畴。除了这里提供的答案,你也可以考虑诸如

之类的解决方案。
  • 自定义库,如

那个FluentValidation图书馆看起来不错。谢谢!我想我在这里使用你的建议。谢谢!
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()
   {
     ...