📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| 101行目: | 101行目: | ||
== ソリューション == | == ソリューション == | ||
==== | ==== 方法 1 : static / readonly ==== | ||
<code>HttpClient</code>クラスは、<code>private</code>キーワードおよび<code>static</code>キーワードを指定したプロパティとして持つ必要がある。<br> | <code>HttpClient</code>クラスは、<code>private</code>キーワードおよび<code>static</code>キーワードを指定したプロパティとして持つ必要がある。<br> | ||
<br> | <br> | ||
| 107行目: | 107行目: | ||
HttpClientを使用した実装をする時は、インスタンスを静的変数(static)にして使用するとの記載がある。<br> | HttpClientを使用した実装をする時は、インスタンスを静的変数(static)にして使用するとの記載がある。<br> | ||
<br> | <br> | ||
まず、<code>HttpClient</code>クラスのオブジェクトを生成する。<br> | まず、<code>HttpClient</code>クラスのオブジェクトを生成する。<br> | ||
この時、タイムアウトの設定等はコンストラクタで行う必要がある。<br> | この時、タイムアウトの設定等はコンストラクタで行う必要がある。<br> | ||
| 145行目: | 144行目: | ||
また、1つの<code>HttpClient</code>クラスは1つのソケット(1つのホスト)として使用した方がよいため、<br> | また、1つの<code>HttpClient</code>クラスは1つのソケット(1つのホスト)として使用した方がよいため、<br> | ||
異なるホストにもリクエストを投げる場合は、別の<code>HttpClient</code>クラスのオブジェクトを生成する方がよい。<br> | 異なるホストにもリクエストを投げる場合は、別の<code>HttpClient</code>クラスのオブジェクトを生成する方がよい。<br> | ||
<br> | |||
==== 方法 2 : HttpClientFactory (単一のベースURI) ==== | |||
* 依存性注入 (DI) の設定 | |||
*: Host.CreateDefaultBuilderメソッドを使用して、.NETの標準的なDIコンテナを設定する。 | |||
*: サービスの登録はConfigureServicesメソッドで行う。 | |||
*: 異なるライフタイムスコープ (Transient, Scoped, Singleton) から適切なものを選択する。 | |||
<br> | |||
HttpClientFactoryでは、2つのパターンがある。<br> | |||
* 名前付きHttpClient | |||
*: services.AddHttpClient("github", ...) で登録する。 | |||
*: IHttpClientFactory.CreateClient("github")で取得する。 | |||
*: 同じ名前で登録されたクライアントは同じ設定を共有する。 | |||
*: <br> | |||
* 型付きHttpClient | |||
*: services.AddHttpClient<GitHubService>メソッドで登録する。 | |||
*: コンストラクタインジェクションで自動的に注入する。 | |||
*: サービスごとに特化した実装が可能になる。 | |||
<br> | |||
Nugetを使用して、以下に示すライブラリをインストールする。<br> | |||
* Microsoft.Extensions.Http | |||
* Microsoft.Extensions.Hosting | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
using System; | |||
using System.Threading.Tasks; | |||
using System.Net.Http; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
// GenericHostを使用してアプリケーションを構築 | |||
// これにより、依存性注入、構成、ログ等の機能が利用可能になる | |||
var host = Host.CreateDefaultBuilder(args).ConfigureServices((context, services) => { | |||
// 方法 1 : 名前付きHttpClientを使用する場合 | |||
// 名前付きHttpClientの登録 | |||
// "github"という名前で、GitHubのAPIにアクセスするためのHttpClientを設定 | |||
services.AddHttpClient("github", client => { | |||
// ベースとなるURIを設定 | |||
client.BaseAddress = new Uri("https://api.github.com/"); | |||
// User-Agentヘッダを設定 (GitHubのAPIでは必須) | |||
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); | |||
}); | |||
// 方法 2 : 型付きHttpClientを使用する場合 | |||
// 型付きHttpClientの登録 | |||
// GitHubServiceクラスに特化したHttpClientを自動的に注入 | |||
services.AddHttpClient<GitHubService>(); | |||
// ExampleServiceをDIコンテナに登録 | |||
// TransientスコープでサービスをDIコンテナに登録(毎回新しいインスタンスが作成される) | |||
services.AddTransient<IExampleService, ExampleService>(); | |||
}).Build(); | |||
// DIコンテナからサービスを取得し、実行 | |||
var service = host.Services.GetRequiredService<IExampleService>(); | |||
await service.RunExample(); | |||
} | |||
} | |||
/// <summary> | |||
/// 型付きHttpClientを使用するサービスクラス | |||
/// GitHubのAPIに特化した操作を提供 | |||
/// </summary> | |||
public class GitHubService | |||
{ | |||
private readonly HttpClient _httpClient; | |||
// コンストラクタインジェクション | |||
// DIコンテナにより、設定済みのHttpClientが自動的に注入される | |||
public GitHubService(HttpClient client) | |||
{ | |||
_httpClient = client; | |||
// このHttpClientインスタンスに対する固有の設定 | |||
_httpClient.BaseAddress = new Uri("https://api.github.com/"); | |||
_httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); | |||
} | |||
/// <summary> | |||
/// GitHubのAPIからデータを取得する | |||
/// </summary> | |||
/// <returns>API応答の文字列</returns> | |||
public async Task<string> GetApiResponse() | |||
{ | |||
// dotnet/runtimeリポジトリの情報を取得 | |||
return await _httpClient.GetStringAsync("repos/dotnet/runtime"); | |||
} | |||
} | |||
/// <summary> | |||
/// サービスのインターフェース定義 | |||
/// 依存性の注入とテストを容易にするために使用 | |||
/// </summary> | |||
public interface IExampleService | |||
{ | |||
Task RunExample(); | |||
} | |||
/// <summary> | |||
/// HttpClientFactoryの使用例を示すサービスクラス | |||
/// 名前付きHttpClientと型付きHttpClientの両方の使用例を提供 | |||
/// </summary> | |||
public class ExampleService : IExampleService | |||
{ | |||
private readonly IHttpClientFactory _clientFactory; | |||
private readonly GitHubService _githubService; | |||
/// <summary> | |||
/// コンストラクタで依存関係を注入 | |||
/// </summary> | |||
/// <param name="clientFactory">HttpClientFactory - 名前付きクライアントの作成に使用</param> | |||
/// <param name="githubService">GitHubService - 型付きHttpClientの例として使用</param> | |||
public ExampleService(IHttpClientFactory clientFactory, GitHubService githubService) | |||
{ | |||
_clientFactory = clientFactory; | |||
_githubService = githubService; | |||
} | |||
/// <summary> | |||
/// HttpClientFactoryの両方の使用パターンを実演 | |||
/// </summary> | |||
public async Task RunExample() | |||
{ | |||
// 方法 1 : 名前付きHttpClientの使用例 | |||
try | |||
{ | |||
// "github"という名前で設定されたHttpClientを取得 | |||
var client = _clientFactory.CreateClient("github"); | |||
var response = await client.GetStringAsync("repos/dotnet/runtime"); | |||
Console.WriteLine("Named HttpClient Response:"); | |||
Console.WriteLine(response.Substring(0, 200) + "..."); | |||
} | |||
catch (Exception ex) | |||
{ | |||
Console.WriteLine($"Named client error: {ex.Message}"); | |||
} | |||
// // 方法 2 : 型付きHttpClientの使用例 | |||
try | |||
{ | |||
// 注入されたGitHubServiceを使用 | |||
var response = await _githubService.GetApiResponse(); | |||
Console.WriteLine("Typed HttpClient Response:"); | |||
Console.WriteLine(response.Substring(0, 200) + "..."); | |||
} | |||
catch (Exception ex) | |||
{ | |||
Console.WriteLine($"Typed client error: {ex.Message}"); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 方法 3 : HttpClientFactory (複数のベースURI) ==== | |||
<br><br> | <br><br> | ||