当返回对象时如何抛出异常?

6

我有一个Web方法,作为Web服务的一部分:

public List<CustomObject> GetInformation() {
    List<CustomObject> cc = new List<CustomObject>();

    // Execute a SQL command
    dr = SQL.Execute(sql);

    if (dr != null) {
       while(dr.Read()) {
           CustomObject c = new CustomObject()
           c.Key = dr[0].ToString();
           c.Value = dr[1].ToString();
           c.Meta = dr[2].ToString();
           cc.Add(c);
       }
    }
    return cc;
}

我希望将错误处理纳入其中,以便如果未返回任何行或者drnull或者发生其他错误,我希望以错误描述的形式返回异常。但是,如果该函数返回List<CustomObject>,当出现问题时如何向客户端返回错误消息呢?


4
异常改变了代码的正常执行流程。方法可能会正常退出并返回其值,也可能通过异常退出,这时将不会有任何返回值。如果你在该方法内捕获和处理异常,可以返回一个 Tuple<List<CustomObject>, Exception>,但我从未见过这么做的情况。 - hatchet - done with SOverflow
2个回答

4
我将创建一个包装类,其中既包括您的List自定义对象,也包括另一个属性的错误信息。
public class MyCustomerInfo
{
  public List<CustomObject> CustomerList { set;get;}
  public string ErrorDetails { set;get;}

  public MyCustomerInfo()
  {
    if(CustomerList==null)
       CustomerList=new List<CustomObject>();  
  }
}

现在,我将从我的方法中返回一个该类的对象。
public MyCustomerInfo GetCustomerDetails()
{
  var customerInfo=new MyCustomerInfo();

  // Execute a SQL command
    try
    {
      dr = SQL.Execute(sql);

      if(dr != null) {
         while(dr.Read()) {
           CustomObject c = new CustomObject();
           c.Key = dr[0].ToString();
           c.Value = dr[1].ToString();
           c.Meta = dr[2].ToString();
           customerInfo.CustomerList.Add(c);
         }
      }
      else
      {
          customerInfo.ErrorDetails="No records found";
      } 
   }
   catch(Exception ex)
   {
       //Log the error in this layer also if you need it.
       customerInfo.ErrorDetails=ex.Message;
   }     
  return customerInfo;    
}

编辑:为了使其更具可重用性和通用性,创建一个单独的类来处理这个问题是一个好主意。我会把它作为一个属性放在我的基类中。

public class OperationStatus
{
  public bool IsSuccess { set;get;}
  public string ErrorMessage { set;get;}
  public string ErrorCode { set;get;}
  public string InnerException { set;get;}
}
public class BaseEntity
{
  public OperationStatus OperationStatus {set;get;}
  public BaseEntity()
  {
      if(OperationStatus==null)
         OperationStatus=new OperationStatus();
  } 
}

让您的所有子实体参与事务并从这个基类继承

   public MyCustomInfo : BaseEntity
   {
      public List<CustomObject> CustomerList { set;get;}
      //Your constructor logic to initialize property values
   } 

现在,您可以根据需要设置OperationStatus属性的值。
public MyCustomInfo GetThatInfo()
{
    var thatObject=new MyCustomInfo();
    try
    {
       //Do something 
       thatObject.OperationStatus.IsSuccess=true;
    }
    catch(Exception ex)
    {
      thatObject.OperationStatus.ErrorMessage=ex.Message;
      thatObject.OperationStatus.InnerException =(ex.InnerException!=null)?ex.InnerException:"";
    }
    return thatObject;
}

考虑创建一个“StatusInfo”或类似的对象,用于保存错误代码+错误详情。原因有两个:1)ErrorCode=0比检查null/空白消息更好(在我看来);2)这个简单的类是可重复使用的,并且成为您与调用者契约的较大模式的一部分。 - brian chandley
@brianchandley:是的。我只是这样展示,以便OP能够理解。通常我会有不同的类来处理OperationStatus。我猜更新一下是个好主意。我会去做的。 - Shyju
+1 感谢您提供的两种方法。我的代码仍处于早期阶段,因此我采用了更通用可重用的方法,我觉得非常优美。再次感谢您。 - Legend
customerInfo.ErrorDetails=ex.Message; 是一个巨大的安全风险。您正在向服务客户泄露Web服务实现细节。最好将其更改为 customerInfo.ErrorDetails="内部服务错误"; 并将实际异常消息写入数据库。 - Lightman

0

你正在使用WCF吗?如果是的话,考虑使用faults


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接