捕获多个自定义FaultException类型

时间:2012-10-16 12:17:44

标签: c# .net wcf exception

在我的WCF服务上,我有几种自定义错误类型。一种名为BaseFault的抽象类型及其两种实现,称为TypeOneFault和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 "";
}

我的服务界面就像这样

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

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

   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 (FaultException<BaseFault> fex)
    {
         BaseFault Ex = fex.Detail;
         twoEx.{property} ...
    }    

如果有一个这样的块可以捕获我在服务器上抛出的任何异常并通过抽象获得正确的类的详细信息,那将是很好的。通过以上操作我得到一个错误。 mscorlib.dll`

中发生了An unhandled exception of type 'System.ServiceModel.FaultException 1'

我是否需要更改以使其工作,或者我必须满足于多个catch块?

2 个答案:

答案 0 :(得分:4)

FaultException<T>继承自FaultException,因此您可以捕获基本类型:

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块不同,这可以重构:

    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;
    }
}

如果你的两个故障类别没有关系,那就尽可能地去了。但是,如果他们从一个共同的基础继承,那么你可以进一步重构:

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
}

答案 1 :(得分:2)

为了方便起见,使用FastMember这样的事情怎么样,但你可以使用动态和一些try / catch块获得相同的效果:

try
{
    client.ThisMethodHasFault("");
}
catch (FaultException e)
{
    var accessor = TypeAccessor.Create(e.GetType());
    var detail = accessor.GetMembers().Any(x => x.Name == "Detail")
                     ? accessor[e, "Detail"] as BaseFault
                     : null;

    if (detail != null)
    {
        // Do processing here
    }
    else
    {
        throw;
    }
}