Created
February 20, 2026 12:18
-
-
Save yamamaya/5c93007175fcf0cebd5e6d831fd3e3ee to your computer and use it in GitHub Desktop.
DIの練習・HTTPクライアントの実装
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Net.Sockets; | |
| using System.Text; | |
| // DIの練習として、HTTPクライアントを実装する。 | |
| // DI(Dependency Injection)とは、クラスが必要とする依存関係を外部から注入することで、クラスの柔軟性とテスト容易性を向上させる設計パターンである。 | |
| // この例では、WebFetcherクラスがHTTPプロトコルを使用してウェブページを取得するための依存関係を注入する。 | |
| // WebFetcherはIProtocolに依存しているが、具体的なプロトコルの実装には依存していない。 | |
| // 更に、Http11ProtocolはITransportに依存しているが、具体的なトランスポートの実装には依存していない。 | |
| // これにより、具体的な実装との結合度が低くなり、柔軟性とテスト容易性が向上する。 | |
| namespace DI_practice1_http { | |
| internal class Program { | |
| static void Main( string[] args ) { | |
| // 依存関係の構築 | |
| // TcpTransportを作成 | |
| var transport = new TcpTransport(); | |
| // TcpTransportを注入してHttp11Protocolを作成 | |
| var protocol = new Http11Protocol( transport ); | |
| // Http11Protocolを注入してWebFetcherを作成 | |
| var fetcher = new WebFetcher( protocol ); | |
| // WebFetcherを使用してexample.comのトップページを取得 | |
| fetcher.Fetch( "example.com", "/" ); | |
| } | |
| } | |
| /// <summary> | |
| /// ホストとパスを指定してウェブページを取得するクラス | |
| /// </summary> | |
| /// <remarks> | |
| /// WebFetcherはプロトコル層に依存しているが、具体的な実装には依存していない | |
| /// </remarks> | |
| class WebFetcher { | |
| private readonly IProtocol _protocol; | |
| /// <summary> | |
| /// WebFetcherのコンストラクタ | |
| /// </summary> | |
| /// <remarks> | |
| /// IProtocolを注入する | |
| /// </remarks> | |
| /// <param name="protocol"></param> | |
| public WebFetcher( IProtocol protocol ) { | |
| _protocol = protocol; | |
| } | |
| public void Fetch( string host, string path ) { | |
| var response = _protocol.Request( host, path ); | |
| Console.Write( response ); | |
| } | |
| } | |
| /// <summary> | |
| /// プロトコル層の契約 | |
| /// </summary> | |
| interface IProtocol { | |
| /// <summary> | |
| /// ホストとパスを指定してリクエストを送信し、レスポンスを文字列で返す | |
| /// </summary> | |
| /// <param name="host"></param> | |
| /// <param name="path"></param> | |
| /// <returns></returns> | |
| string Request( string host, string path ); | |
| } | |
| /// <summary> | |
| /// HTTP/1.1の実装 | |
| /// </summary> | |
| /// <remarks> | |
| /// Http11ProtocolはIProtocolに依存しているが、具体的なトランスポートの実装には依存していない | |
| /// </remarks> | |
| class Http11Protocol : IProtocol { | |
| private readonly ITransport _transport; | |
| /// <summary> | |
| /// Http11Protocolのコンストラクタ | |
| /// </summary> | |
| /// <remarks> | |
| /// ITransportを注入する | |
| /// </remarks> | |
| /// <param name="transport"></param> | |
| public Http11Protocol( ITransport transport ) { | |
| _transport = transport; | |
| } | |
| /// <summary> | |
| /// Requestの実装 | |
| /// </summary> | |
| /// <param name="host"></param> | |
| /// <param name="path"></param> | |
| /// <returns></returns> | |
| public string Request( string host, string path ) { | |
| var stream = _transport.Connect( host, 80 ); | |
| var request = $"GET {path} HTTP/1.1\r\nHost: {host}\r\nConnection: close\r\n\r\n"; | |
| stream.Write( Encoding.ASCII.GetBytes( request ) ); | |
| var sb = new StringBuilder(); | |
| var buffer = new byte[ 4096 ]; | |
| int bytesRead; | |
| while ( ( bytesRead = stream.Read( buffer, 0, buffer.Length ) ) > 0 ) { | |
| sb.Append( Encoding.ASCII.GetString( buffer, 0, bytesRead ) ); | |
| } | |
| return sb.ToString(); | |
| } | |
| } | |
| /// <summary> | |
| /// トランスポート層の契約 | |
| /// </summary> | |
| interface ITransport { | |
| /// <summary> | |
| /// ホストとポートを指定して接続し、ストリームを返す | |
| /// </summary> | |
| /// <param name="host"></param> | |
| /// <param name="port"></param> | |
| /// <returns></returns> | |
| Stream Connect( string host, int port ); | |
| } | |
| /// <summary> | |
| /// TCPを使用したトランスポートの実装 | |
| /// </summary> | |
| class TcpTransport : ITransport { | |
| /// <summary> | |
| /// Connectの実装 | |
| /// </summary> | |
| /// <param name="host"></param> | |
| /// <param name="port"></param> | |
| /// <returns></returns> | |
| public Stream Connect( string host, int port ) { | |
| var client = new TcpClient( host, port ); | |
| return client.GetStream(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment