捕获多个自定义的FaultException类型多个、自定义、类型、FaultException

2023-09-06 13:08:53 作者:镜子别哭。

在我的WCF服务,我有几个自定义故障类型。一个叫BaseFault和它的两个实现抽象类型称为TypeOneFault和TypeTwoFault

On my WCF service I have a couple of custom fault types. An abstract type called BaseFault and two implementations of it called TypeOneFault and TypeTwoFault

我在服务端像这样

public string ThisMethodHasFault(string eType)
{
    if (eType.Contains("One"))
    {
        TypeOneFault one = new TypeOneFault("TypeOneFault thrown");
        throw new FaultException<TypeOneFault>(one, new FaultReason(new FaultReasonText("Fault reason here")));
    }
    else
    {
        TypeTwoFault two = new TypeTwoFault("TypeTwoFault thrown");
        throw new FaultException<TypeTwoFault>(two, new FaultReason(new FaultReasonText("Fault reason here")));
    }

    return "";
}

我的服务界面是这样的

My Service interface is like this

[OperationContract]
[FaultContract(typeof(TypeOneFault ))]
[FaultContract(typeof(TypeTwoFault ))]
string ThisMethodHasFault(string eType);

在客户端我有,我抓住它是这样一个测试WinForm应用程序

On the client side I have a test winform application where I catch it like this

   MyServiceClient client = new MyServiceClient();

   try
    {
        client.ThisMethodHasFault(""); //get value from user

    }
    catch (FaultException<TypeOneFault>  ox)
    {
         TypeOneFault oneEx = ox.Detail;
         oneEx.{property} ...

    }   
    catch (FaultException<TypeTwoFault>  tx)
    {
         TypeTwoFault twoEx = tx.Detail;
         twoEx.{property} ...
    }    

问:

我似乎能够通过这样做,而不是减少catch块的数量

I cant seem to be able to reduce the number of catch blocks by doing this instead

    catch (FaultException<BaseFault> fex)
    {
         BaseFault Ex = fex.Detail;
         twoEx.{property} ...
    }    

这本来是不错的,可以捕捉到我扔在服务器上,并通过抽象我得到正确的类的详细信息任何异常这样的一个块。通过这样做上述我得到一个错误。 类型的未处理的异常'System.ServiceModel.FaultException 1发生在mscorlib.dll`

It would have been nice to have one such block that could capture any exception that I throw on the server and through abstraction I get the right class's details. By doing the above I get an error. An unhandled exception of type 'System.ServiceModel.FaultException1' occurred in mscorlib.dll`

有什么我需要改变,使这项工作或做我必须内容与多个catch块而已?的

推荐答案

的FaultException&LT; T&GT; 的FaultException 继承,这样你就可以赶上的基本类型,而不是:

FaultException<T> inherits from FaultException, so you can catch the base type instead:

catch(FaultException ex) {
    if(ex is FaultException<TypeOneFault>) {
        var detail = ((FaultException<TypeOneFault>) ex).Detail;
        // process it
    } else if(ex is FaultException<TypeTwoFault>) {
        var detail = ((FaultException<TypeTwoFault>) ex).Detail;
        // process it
    } else {
        // unexpected error
        throw;
    }
}

不同的是两个独立的catch块,这可重构:

Unlike the two separate catch blocks, this can be refactored:

    catch(FaultException ex) {
        if(!ProcessFault(ex)) {
            throw;
        }

bool ProcessFault(FaultException ex) {
    if(ex is FaultException<TypeOneFault>) {
        var detail = ((FaultException<TypeOneFault>) ex).Detail;
        // process it
        return true;
    } else if(ex is FaultException<TypeTwoFault>) {
        var detail = ((FaultException<TypeTwoFault>) ex).Detail;
        // process it
        return true;
    } else {
        // unexpected error
        return false;
    }
}

如果你的两个故障类没有关系,那就是只要你可以走了。但是,如果他们来自一个共同的基础继承,那么你就可以进一步重构:

If your two fault classes are not related, then that's as far as you can go. However, if they inherit from a common base, then you can refactor further:

bool ProcessFault(FaultException ex) {
    if(ex is FaultException<TypeOneFault>) {
        ProcessFault(((FaultException<TypeOneFault>) ex).Detail);
        return true;
    } else if(ex is FaultException<TypeTwoFault>) {
        ProcessFault(((FaultException<TypeTwoFault>) ex).Detail);
        return true;
    } else {
        // unexpected error
        return false;
    }
}

void ProcessFault(BaseFault detail) {
    // process it
}