AutoIoc 1.3.0

dotnet add package AutoIoc --version 1.3.0
NuGet\Install-Package AutoIoc -Version 1.3.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AutoIoc" Version="1.3.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AutoIoc --version 1.3.0
#r "nuget: AutoIoc, 1.3.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install AutoIoc as a Cake Addin
#addin nuget:?package=AutoIoc&version=1.3.0

// Install AutoIoc as a Cake Tool
#tool nuget:?package=AutoIoc&version=1.3.0

AutoIoc

NuGet Status NuGet

Are you familiar with adding services, options/configurations from app settings, and HTTP client classes to your dependency injection container? Examples of what I mean:

services.AddTransient<IFooBarService, FooBarService>();

services.AddOptions<HelloWorldConfiguration>()
    .Configure<IConfiguration>((settings, config) => { config.GetSection("HelloWorld").Bind(settings); });
    
services.AddTransient<AuthDelegatingHandler>();

services.AddHttpClient<IAnimeClient, AnimeClient>()
    .AddHttpMessageHandler<AuthDelegatingHandler>();
    
services.AddRefitClient<IColorClient>()
    .ConfigureHttpClient(c => {...})
    .AddHttpMessageHandler<AuthDelegatingHandler>();

Then your code eventually grows to look like:

services.AddSingleton<IService1, Service1>()
    .AddSingleton<IService2, Service2>()
    .AddSingleton<IService3, Service3>()
    /* pretend there are 100s of these */
    .AddSingleton<IService99, Service99>()
    .AddSingleton<IService100, Service100>();

Well this package makes that much easier. It will scan your assembly and fine items that need to be added to your DI container based on attributes.

NuGet Installation

Install the AutoIoc NuGet package:

dotnet add package AutoIoc

Usage

Add the following to your Startup.cs:

services.AddAutoIoc(configuration, assembly);

Services

Add services based on the lifetime you'd like to have them have:

public interface IExample {}
  • Transient lifetime:

    // always add it to the concrete class as that is where your behavior lives
    [TransientService]
    public class Example : IExample {} 
    
    // this is equivalent to
    services.AddTransient<IExample, Example>();
    
  • Scoped lifetime:

    // always add it to the concrete class as that is where your behavior lives
    [ScopedService]
    public class Example : IExample {} 
    
    // this is equivalent to
    services.AddScoped<IExample, Example>();
    
  • Singleton lifetime:

    // always add it to the concrete class as that is where your behavior lives
    [SingletonService]
    public class Example : IExample {} 
    
    // this is equivalent to
    services.AddSingleton<IExample, Example>();
    

Options

Create your POCO class and add the following attribute with the desired app settings key:

// This will automatically bind the the key `Example`
[BindOptions]
public class ExampleConfiguration
{
    public string Foo { get; set; }
    public string Bar { get; set; }
}

// This will bind the the key `Foo:Bar`
[BindOptions("Foo:Bar")]
public class ExampleConfiguration
{
    public string Foo { get; set; }
    public string Bar { get; set; }
}

// now inject where desired
public class BananaService
{
    private readonly ExampleConfiguration _exampleConfiguration;
    
    public BananaService(IOptions<ExampleConfiguration> exampleConfigurationOptions)
    {
        _exampleConfiguration = exampleConfigurationOptions.Value;
    }
}

HTTP Client Class

Typical Route

Normally I see developer creating a client class that injects a name HTTP client from the factory like as follows:

public interface IDbzClient{}
public class DbzClient : IDbzClient
{
    private readonly HttpClient _httpClient;
    
    public DbzClient(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
}

// add to your DI container
services.AddHttpClient<IDbzClient, DbzClient>();

Why not just attribute it?

public interface IDbzClient {}

// always add it to the implementation since this is where your behavior lives
[HttpClient]
public class DbzClient : IDbzClient {}
Refit Route

Love using Refit? Me too! Go ahead and add one extra attribute to your interface so you won't need to add another line to your Startup.cs:

[HttpClient]
public class IDbzClient
{
    [Get("/foo/bar")]
    Task<ApiResponse<string>> GetFooBarAsync();
}

// now inject where desired
public class BananaService
{
    private readonly IDbzClient _dbzClient;
    
    public BananaService(IDbzClient dbzClient)
    {
        _dbzClient = dbzClient;
    }
    
    public async void CallItAsync()
    {
        var result = await _dbzClient.GetFooBarAsync();
        
        if(result.IsSuccessStatusCode)
        {
            Console.WriteLine(result.Content);
        }
    }
}
Prerequisites

This will look for the BaseAddress and TimeoutSeconds (OPTIONAL) keys in your appsettings under the default parent key of your client's name minus the *Client postfix. For example, if your client's interface is IGoosfrabaClient, then next your settings as follows:

{
  "Goosfraba": {
    "BaseAddress": "https://goosfraba.com",
    "TimeoutSeconds": 100
  }
}
Delegating Handlers

Need to add delegating handlers? Well this is how you used to do it:

public class AuthDelegatingHandler : DelegatingHandler { }

services.AddTransient<AuthDelegatingHandler>();
services.AddHttpClient<IExampleClient, ExampleClient>()
    .AddHttpMessageHandler<AuthDelegatingHandler>();

Now you can add as many as you want via attributes:

public class AuthDelegatingHandler : DelegatingHandler { }

// examples and order matters
[HttpClient(PrimaryHandler = typeof(CustomPrimaryHandler))]
[HttpClient(typeof(AuthDelegatingHandler), PrimaryHandler = typeof(CustomPrimaryHandler))]
[HttpClient(typeof(AuthDelegatingHandler), typeof(RandomDelegatingHandler), PrimaryHandler = typeof(CustomPrimaryHandler))]
[HttpClient(typeof(AuthDelegatingHandler))]  
[HttpClient(typeof(AuthDelegatingHandler), typeof(RandomDelegatingHandler))]  

Ping me if you want any new features added to the library ❤️

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.3.0 14,226 12/12/2022
1.2.1-beta01 125 12/12/2022
1.2.0 276 12/9/2022
1.1.0 278 12/9/2022
1.0.1 279 12/9/2022
1.0.0 282 12/7/2022
0.0.0-alpha01 129 12/7/2022

Providing a default JSON serializer for ReFit clients which can parse strings as numbers and enums