在发生未处理的异常后,我可以返回失败方法的执行吗?



我有一个ASP。. NET网站,其中包含一些WCF服务。我已经连接到Application_Error事件,因此可以记录任何未处理的异常。

我真正想做的是将执行传递回被调用的方法,这样我就可以向客户端返回一些有意义的东西,而不是抛出FaultException。

我知道我可以在try/catch块中包装每个单独的服务调用,但这意味着在每个方法中都有大量的样板代码。我真正想做的是有一个中央的包罗一切的方法,如Application_Error,但随后允许单个服务调用收回控制权并向客户端返回一些有意义的东西。

这可能吗?

注:如果有人认为我这样做是错误的,背景是我在我的c# WCF代码中实现了面向铁路的编程。其思想是,如果有异常,我返回一个适当的对象,其中包含详细信息,以及其他有用的东西。与让WCF服务抛出异常相比,这是一种更加可控的处理这种情况的方法。

如果你想做一些类似于rop风格的事情,那么你可以这样做(来自Jeff Bridgman的建议的可失败名称)。

首先按如下方式创建抽象基类…

public abstract class Failable<T> {
}
public abstract class Failable {
}

接下来,根据这些创建具体的类来表示成功和失败。我为它们分别添加了一个泛型和非泛型版本,这样你就可以处理返回值和void值的服务调用了…

public class Success<T> : Failable<T> {
  public Success(T value) {
    Value = value;
  }
  public T Value { get; set; }
}
public class Success : Failable {
}
public class Failure<T> : Failable<T> {
  public Failure(Exception value) {
    Value = value;
  }
  public Exception Value { get; set; }
}
public class Failure : Failable {
  public Failure(Exception value) {
    Value = value;
  }
  public Exception Value { get; set; }
}

然后几个辅助方法会给你你想要的…

public Failable<T> DoFailableAction<T>(Func<T> f) {
  Failable<T> result;
  try {
    T fResult = f();
    result = new Success<T>(fResult);
  }
  catch (Exception ex) {
    result = new Failure<T>(ex);
    // Do logging, etc here...
  }
  return result;
}
public Failable DoFailableAction(Action f) {
  Failable result;
  try {
    f();
    result = new Success();
  }
  catch (Exception ex) {
    result = new Failure(ex);
    // Do logging, etc here...
  }
  return result;
}
要使用这些,假设您有您的WCF服务。您将服务调用封装在helper方法中…
Failable<Person> p = failableHelpers.DoFailableAction(() => service.GetPerson(1));

…其中failableHelpers是包含上述两个helper方法的类的实例。

然后,您可以检查呼叫是否成功或失败,并采取适当的行动…

if (p is Success<Person>) {
  Person p = ((Success<Person>)p).Value;
  Debug.WriteLine("Value is Success, and the person is " + p.FirstName + " " + p.Surname);
} else {
  Exception ex = ((Failure<Person>)p).Value;
  Debug.WriteLine("Value is Failure, and the message is " + ex.Message);
}

如果你的service method是void,你可以使用非泛型的变体…

Person jim = new Person(1, "Jim", "Spriggs");
Failable saveResult = failableHelpers.DoFailableAction(() => service.Update(jim));

您还没有完全达到您想要的效果,因为在每个服务方法中仍然有一些样板代码,但是非常少。不像方法上的属性那么简单,但是这种方法实现起来要简单得多,并且适用于任何级别,无论是存储库、业务逻辑、WCF服务、客户端等等。属性方法只适用于WCF。

这种方法的好处是,它将检查服务调用是否成功的责任放在了WCF服务(或其他)的消费者身上,并采取适当的行动。这是一种函数式风格,可以产生更加健壮的代码,因为您几乎不能忽略异常,而不像非函数式编程,在非函数式编程中,您可能只是在假定没有任何问题的情况下获取服务的结果。这很好,直到出了问题!

希望对你有帮助。

最新更新