Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion to add support for dependency injection's IHttpClientFactory. #54

Closed
AhmedZaki99 opened this issue Jun 12, 2024 · 0 comments · Fixed by #56
Closed

Suggestion to add support for dependency injection's IHttpClientFactory. #54

AhmedZaki99 opened this issue Jun 12, 2024 · 0 comments · Fixed by #56

Comments

@AhmedZaki99
Copy link
Contributor

AhmedZaki99 commented Jun 12, 2024

When this library is used by applications with dependency injection configured, HttpClients should be created with the IHttpClientFactory. But our TodoistRestClient keeps creating new instances of HttpClient every time it is instantiated, which is not recommended.

I suggest then we add the option to use IHttpClientFactory when it's available by making the following changes:

  1. Add a constructor overload for TodoistRestClient that takes an HttpClient instance as an argument:
public TodoistRestClient(string token, HttpClient httpClient)
{
    _httpClient = httpClient;

    _httpClient.BaseAddress = new Uri("https://api.todoist.com/sync/v9/");
    if (!string.IsNullOrEmpty(token))
    {
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    }
}
  1. Create an ITodoistClientFactory interface and TodoistClientFactory implementation to inject into the DI container, and use the provided IHttpClientFactory:
public interface ITodoistClientFactory
{
    TodoistClient CreateClient(string token);
}

internal sealed class TodoistClientFactory : ITodoistClientFactory
{
    private readonly IHttpClientFactory _httpClientFactory;

    public TodoistClientFactory(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public TodoistClient CreateClient(string token)
    {
        var httpClient = _httpClientFactory.CreateClient();
        var todoistRestClient = new TodoistRestClient(token, httpClient);

        return new TodoistClient(todoistRestClient);
    }
}
  1. Add an extension method to inject both the ITodoistClientFactory and IHttpClientFactory:
public static class TodoistServiceCollectionExtensions
{
    public static IServiceCollection AddTodoistClient(this IServiceCollection services)
    {
        services.AddHttpClient();
        services.AddSingleton<ITodoistClientFactory, TodoistClientFactory>();

        return services;
    }
}

That way, our TodoistClient can be instantiated the same way as HttpClient, using the factory pattern.

Usage:

  • Service configuration (e.g. program.cs):
var builder = WebApplication.CreateBuilder(args);

builder.Service.AddTodoistClient();
  • In other services (e.g. asp.net core controllers):
public class ExampleController : Controller
{
    private readonly ITodoistClientFactory _todoistClientFactory;

    public ExampleController(ITodoistClientFactory todoistClientFactory)
    {
        _todoistClientFactory = todoistClientFactory;
    }

    public IActionResult ExampleAction()
    {
        ITodoistClient client = _todoistClientFactory.CreateClient("API token");

        // Use the client to interact with the Todoist API.
        //...
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant