3

次のように実装するとします。

public class SomeServiceWrapper
{
    public string GetSomeString()
    {
        try
        {
            //Do Something
        }
        catch (IOException e)
        {
            throw new ServiceWrapperException("Some Context", e);
        }
        catch (WebException e)
        {
            throw new ServiceWrapperException("Some Context", e);
        }
    }
}

上記の意図は、 の消費者がGetSomeStringをキャッチするだけでよいようにすることServiceWrapperExceptionです。

同様の非同期動作でこれを拡張するには、次のアプローチを検討してください。

public Task<string> GetSomeStringAsync()
{
    Task<string>.Factory doSomething = ...
    return doSomething.ContinueWith(x => 
    {
        if (x.IsFaulted)
        {
             if (x.Exception.InnerExceptions.Count() > 1)
             {
                 throw new AggregateException(x.Exception);
             }

             var firstException = x.Exception.InnerExceptions[0];
             if (typeof(firstException) == typeof(IOException)
                 || typeof(firstException) == typeof(WebException))
             {
                 throw new ServiceWrapperException("Some Context", firstException);
             }
        }

        return x.Result;
    }
} 

例外をラップするためのこの同期アプローチは、非同期アプローチには自然に適合しません。

SomeServiceWrapperコンシューマーの例外処理コードを単純化して、とTradeLoaderExceptionの両方IOExceptionではなく処理するだけで済むようにするために、 の作成者は何ができるWebExceptionでしょうか?

4

1 に答える 1

2

私はそれをほとんど行う拡張メソッドを作成しました。使用法:

public static Task<string> GetSomeStringAsync()
{
    var doSomething = Task.Factory.StartNew(() => "bar");
    return doSomething.WrapExceptions(typeof(IOException), typeof(WebException));
}
  1. 継続で元のタスクを返すだけです。
  2. ServiceWrapperException を AggregateException のように複数の例外を保持するように変更してから、最初の部分を変更することをお勧めします。

メソッド:

public static Task<TResult> WrapExceptions<TResult>(this Task<TResult> task, params Type[] exceptionTypes)
{
    return task.ContinueWith(_ =>
    {
        if (_.Status == TaskStatus.RanToCompletion) return _.Result;

        if (_.Exception.InnerExceptions.Count > 1)
        {
            throw new AggregateException(_.Exception);
        }

        var innerException = _.Exception.InnerExceptions[0];
        if (exceptionTypes.Contains(innerException.GetType()))
        {
            throw new ServiceWrapperException("Some Context", innerException);
        }

        throw _.Exception;
    });
}
于 2013-11-22T19:26:49.650 に答える