Skip to content

Instantly share code, notes, and snippets.

@Stroniax
Created January 23, 2023 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stroniax/c6ffd55b9506d4bfb7feb4036bc895b5 to your computer and use it in GitHub Desktop.
Save Stroniax/c6ffd55b9506d4bfb7feb4036bc895b5 to your computer and use it in GitHub Desktop.
Example StrongInject Application Configured HttpClient
// See https://aka.ms/new-console-template for more information
using StrongInject;
using System.Net;
using System.Net.Http.Json;
namespace StrongInjectConfiguredHttpClientExample;
public class Program
{
public async Task Main(string[] args)
{
await using var container = new AppContainer(args);
await container.RunAsync(async program =>
{
await program.UpdateRecords();
});
}
}
// end
public interface IFileReader
{
IAsyncEnumerable<string?> ReadAllLines(string fileName);
}
public class FileReader : IFileReader
{
public async IAsyncEnumerable<string?> ReadAllLines(string fileName)
{
await using var file = File.OpenRead(fileName);
using var reader = new StreamReader(file);
while (!reader.EndOfStream)
{
yield return await reader.ReadLineAsync();
}
}
}
/// <summary>
/// Sends file information to an HTTP endpoint to update some entity.
/// </summary>
public class FileContentHttpClient
{
private readonly HttpClient _http;
public FileContentHttpClient(HttpClient http) => _http = http;
public async Task UpdateRecord(FileContentUpdate update) => await _http.PutAsJsonAsync($"/records/{update.RecordId}", update);
}
/// <summary>
/// Updates global state at some HTTP endpoint, such as tracking when a program ran last.
/// </summary>
public class GlobalStateHttpClient
{
private readonly HttpClient _http;
public GlobalStateHttpClient(HttpClient http) => _http = http;
public async Task UpdateGlobalState(GlobalStateUpdate update) => await _http.PostAsJsonAsync("/applications/check-in", update);
}
public record GlobalStateUpdate(
int UpdatedFileCount,
DateTimeOffset StartTime,
DateTimeOffset CompleteTime,
string Application,
bool HadErrors
);
public record FileContentUpdate(
int RecordId,
DateTimeOffset Posted
// other members...
)
{
public static FileContentUpdate Parse(string line) => throw new NotImplementedException();
}
public record ContentUpdateService(
IFileReader FileReader,
FileContentHttpClient FileContent,
GlobalStateHttpClient GlobalState,
string[] FileNames
)
{
public async Task UpdateRecords()
{
var updatedFileCount = 0;
var start = DateTimeOffset.UtcNow;
try
{
foreach (var fileName in FileNames)
{
updatedFileCount++;
await ProcessFile(fileName);
}
}
catch
{
await UpdateGlobalState(updatedFileCount, start, true);
return;
}
await UpdateGlobalState(updatedFileCount, start, false);
}
private Task UpdateGlobalState(int updatedFileCount, DateTimeOffset start, bool hadErrors)
=> GlobalState.UpdateGlobalState(
new(
updatedFileCount,
start,
DateTimeOffset.UtcNow,
"My-Application",
hadErrors));
public async Task ProcessFile(string fileName)
{
await foreach (var line in FileReader.ReadAllLines(fileName))
{
var record = FileContentUpdate.Parse(line!);
await FileContent.UpdateRecord(record);
}
}
}
[Register<FileReader, IFileReader>]
[Register<ContentUpdateService>]
public partial class AppContainer : IAsyncContainer<ContentUpdateService>
{
[Instance]
private readonly string[] _args;
public AppContainer(string[] args) => _args = args;
[Factory]
public static GlobalStateHttpClient CreateGlobalStateClient()
{
return new GlobalStateHttpClient(
new HttpClient(
new HttpClientHandler()
{
PreAuthenticate = true,
Credentials = new CredentialCache()
{
{ new Uri("http://app-api.com/"), "Negotiate", CredentialCache.DefaultNetworkCredentials }
}
})
{
BaseAddress = new Uri("http://app-api.com/"),
});
}
[Factory]
public static FileContentHttpClient CreateFileContentClient()
{
return new FileContentHttpClient(
new HttpClient(
new HttpClientHandler()
{
Credentials = new NetworkCredential("My-service-accoutn", "securepswd"),
PreAuthenticate = true,
}
)
{
BaseAddress = new Uri("http://record-api.com/"),
}
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment