3

取り組んでいるプロジェクトにコマンド パターンを実装しました。これはほとんど現在の構造です。

public class Response
{
    public bool Success { get; private set; }

    public static Response CreateErrorResponse()
    {
        return new Response { Success = false };
    }
}

public interface ICommand<T> where T : Response
{
    Task<T> ExecuteAsync();
}

public abstract CommandBase : ICommand<T> where T: Response
{
    protected abstract Uri BuildUrl();
    protected abstract Task<T> HandleResponseAsync();

    public async override Task<T> ExecuteAsync()
    {
        var url = BuildUrl();
        var httpClient = new HttpClient();

        var response = await httpClient.GetAsync(url);
        return await HandleResponseAsync(response);
    }
}

HttpClient によってスローされる可能性のある例外を処理したいので、CommandBase.ExecuteAsync を次のように変更したいと思います...

public async override Task<T> ExecuteAsync()
{
    var url = BuildUrl();
    var httpClient = new HttpClient();

    try
    {
        var response = await httpClient.GetAsync(url);
        return await HandleResponseAsync(response);
    }
    catch (HttpRequestException hex)
    {
        return Response.CreateErrorResponse(); // doesn't compile
    }
}

コンパイル エラーは、「Response 型を非同期戻り型 T に変換できません」です。この質問でT.CreateErrorResponse()概説されているように、私は使用できません。

どうすればこれを回避できますか?

反対票を投じる人への編集: このようなライブラリで例外をキャッチすることに同意するかどうかに関係なく、問題は解決しません!

4

2 に答える 2

3

これが最善の解決策(または特定のユースケースで実現可能)であるかどうかはわかりませんが、できることは次のとおりです。

public class Response
{
    public bool Success { get; private set; }
    public ExceptionDispatchInfo ErrorInfo { get; private set; }
    public bool HasFailed
    {
        get { return !Success; }
    }

    public static T CreateErrorResponse<T>(ExceptionDispatchInfo errorInfo) where T : Response, new()
    {
        var response = new T();
        response.Success = false;
        response.ErrorInfo = errorInfo;
        return response;
    }
}

使用法:

catch (HttpRequestException hex)
{
    return Response.CreateErrorResponse<T>(ExceptionDispatchInfo.Capture(hex)); // should compile (I did not check)
}
于 2013-09-01T20:45:47.880 に答える
0

応答を T にキャストできます。編集: 完全なソース コードを追加しました。

public class Response
{
    public bool Success { get; private set; }

    public static Response CreateErrorResponse()
    {
        return new Response { Success = false };
    }
}

public interface ICommand<T> where T : Response
{
     Task<T> ExecuteAsync();
}

public abstract class CommandBase<T> : ICommand<T> where T: Response
{
    protected abstract Uri BuildUrl();
    protected abstract Task<T> HandleResponseAsync();

    public async Task<T> ExecuteAsync()
{
    var url = BuildUrl();
    var httpClient = new System.Net.Http.HttpClient();

    try
    {
        var response = await httpClient.GetAsync(url);
        return null;// await HandleResponseAsync(response);
    }
    catch (Exception hex)
    {
        return (T)Response.CreateErrorResponse(); // doesn't compile
    }
}
}

public async override Task<T> ExecuteAsync()
{
    var url = BuildUrl();
    var httpClient = new HttpClient();

    try
    {
        var response = await httpClient.GetAsync(url);
        return await HandleResponseAsync(response);
    }
    catch (HttpRequestException hex)
    {
        return (T)Response.CreateErrorResponse(); // compiles on liqpad
    }
}
于 2013-09-01T22:14:19.197 に答える