4

背景デザインパターンは、MVP WinフォームのクライアントからWebAPIのを消費する

私は2層アプリケーション構築しています:

  • ティアを1:MVPを使用してのWinFormsアプリケーション(モデル - ビュー - プレゼンター)デザインパターン。
  • 層2:WebAPI RESTfulサービス。

WinformsクライアントはHttpClientを使用してWebAPIサービスを消費します。両方の層が重くのIoCと依存性注入デザイン・パターン

質問のWinformsアプリケーションはWebAPIのサービスからのデータを必要とする

を利用して、プレゼンターはその要求をコーディネートになります。私の質問は、発表者の中でHttpClientを直接使用しますか?プレゼンターをテスト可能に保つために、具体的なHttpClientコールに頼る必要がないことをどのように確認しますか?私は何とかこれもquestionからの一番上の答えを統合することを考えていました。

+0

この質問はhttp://programmers.stackexchange.com/に属しているので、私はこのトピックをオフトピックとして閉じるよう投票しています。 –

答えて

4

私はこれをすべて抽象化しています。

私はサービスの抽象化を持つことになり、プレゼンテーション層で

...

public interface IServiceAgent { 
    Task<SomeResultObject> GetSomething(string myParameter); 
} 

...それは私がウェブAPIから欲しいものを抽象化します。発表者は要求を調整する必要はありません。発表者は、データがどこから来ているかには関心がありません。知っていることは、何かを求めてそれを求める(SoC)ということだけです。これを行うのはサービス代理店の仕事です(SRP)。

サービスエージェントの実装では、データのさまざまなソースへの呼び出しが必要な場合があります。ウェブを含む。したがって、HttpClientを抽象化すると、その実装への結合が緩められます。とのユニットテストを可能にすることによって、あなたがテスト可能なプレゼンターを保つそれらの依存関係を抽象化し

簡単な例のように...

public interface IHttpClient { 
    System.Threading.Tasks.Task<T> GetAsync<T>(string uri) where T : class; 
    System.Threading.Tasks.Task<T> GetAsync<T>(Uri uri) where T : class; 
    //...other members as needed : DeleteAsync, PostAsync, PutAsync...etc 
} 

いくつかの実装例

はこのようになります...

public class MyPresenter { 
    public MyPresenter(IServiceAgent services) {...} 
} 

public class MyDefaultServiceAgent : IServiceAgent { 
    IHttpClient httpClient; 

    public MyDefaultServiceAgent (IHttpClient httpClient) { 
     this.httpClient = httpClient; 
    } 

    public async Task<SomeResultObject> GetSomething(string myParameter) { 
      var url = "http://localhost/my_web_api_endpoint?q=" + myParameter; 
      var result = await httpClient.GetAsync<SomeResultObject>(url); 
      return result; 
    } 
} 

public class MyDefaultHttpClient : IHttpClient { 
    HttpClient httpClient; //The real thing 

    public MyDefaultHttpClient() { 
     httpClient = createHttpClient(); 
    } 

    /// <summary> 
    /// Send a GET request to the specified Uri as an asynchronous operation. 
    /// </summary> 
    /// <typeparam name="T">Response type</typeparam> 
    /// <param name="uri">The Uri the request is sent to</param> 
    /// <returns></returns> 
    public System.Threading.Tasks.Task<T> GetAsync<T>(string uri) where T : class { 
     return GetAsync<T>(new Uri(uri)); 
    } 

    /// <summary> 
    /// Send a GET request to the specified Uri as an asynchronous operation. 
    /// </summary> 
    /// <typeparam name="T">Response type</typeparam> 
    /// <param name="uri">The Uri the request is sent to</param> 
    /// <returns></returns> 
    public async System.Threading.Tasks.Task<T> GetAsync<T>(Uri uri) where T : class { 
     var result = default(T); 
     //Try to get content as T 
     try { 
      //send request and get the response 
      var response = await httpClient.GetAsync(uri).ConfigureAwait(false); 
      //if there is content in response to deserialize 
      if (response.Content.Headers.ContentLength.GetValueOrDefault() > 0) { 
       //get the content 
       string responseBodyAsText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); 
       //desrialize it 
       result = deserializeJsonToObject<T>(responseBodyAsText); 
      } 
     } catch (Exception ex) { 
      Log.Error(ex); 
     } 
     return result; 
    } 

    private static T deserializeJsonToObject<T>(string json) { 
     var result = JsonSerializer.Deserialize<T>(json); 
     return result; 
    } 
} 

擬似/模擬サービス代理店。あなたは、偽の/模擬HTTPクライアントを使ってサービスエージェントをテストすることができます。また、アプリケーションコンポーネントを変更/交換/維持する必要がある場合は、これらのインタフェースの具体的な実装を注入することもできます。

+0

素晴らしい答え、ありがとうございます!サービスエージェントを作成するときは、プレゼンターごとに1つのサービスエージェントを作成するか、モデルごとに1つのサービスエージェントを作成しますか?私はプレゼンターがさまざまな種類のデータを取得するために複数の呼び出しを行う必要があるシナリオについて考えています。さらに、IoCコンテナを使用する場合、適切なサービスエージェントがプレゼンターに注入されていることをどのように保証しますか? – Andrew

+0

あなたの気持ちは変わります。私は通常、ドメインごとに1つのサービスエージェントを持っています。私は可能な限りSRPに固執しようとします。正確な注入を得るために、私はISPを使用する – Nkosi

+0

私はまだ正しいプログラミング技術を学んでいるので、堅実な原則。あなたがISPを使用していると言えば、サービスエージェントごとに異なるインターフェースを作成していますか? – Andrew

関連する問題