Uma maneira melhor de injetar coisas

· 3 min de leitura

Sempre que estou construindo coisas como serviços, repositórios, atributos ou qualquer outra coisa para injetar em minhas aplicações, há uma etapa que devemos realizar, que na verdade é adicionar os serviços à aplicação.

É sempre a mesma coisa, você vai para Program.cs e, em alguma parte do arquivo, adiciona builder.Services.AddScoped<MyService>(); para injetar o serviço.

Algo assim:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

// Repositories
builder.Services.AddScoped<ARepository>(); // 👀
builder.Services.AddScoped<BRepository>(); // 👀

// Services
builder.Services.AddScoped<AService>(); // 👀
builder.Services.AddScoped<BService>(); // 👀
builder.Services.AddScoped<CService>(); // 👀
builder.Services.AddScoped<DService>(); // 👀

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Quer dizer, funciona, mas sou exigente e não gosto muito disso.

Digamos que temos múltiplas injeções de dependência que queremos fazer, e elas não são realmente a mesma coisa, no meu caso isso poderia ser algo como ter uma biblioteca que contém todos os repositórios, outra biblioteca que tem todos os serviços e por último, outra biblioteca que contém atributos.

Nesse caso, você pode imaginar a quantidade de linhas que temos que adicionar ao Program.cs.

Digamos que temos uma biblioteca que contém alguns serviços, se quisermos incluir todos os nossos serviços, temos que trabalhar com IServiceCollection.

Então vamos criar um static class que terá um método static chamado AddServices que retorna um IServiceCollection.

Neste caso, será denominado IServiceCollectionServicesExtensions.

/// <summary>
/// IServiceCollectionServicesExtensions class
/// </summary>
public static class IServiceCollectionServicesExtensions
{
    /// <summary>
    /// AddCoreServices
    /// </summary>
    /// <param cref="IServiceCollection" name="services">Parameter for <see cref="IServiceCollection"/></param>
    /// <returns>An object of type <see cref="IServiceCollection"/></returns>
    public static IServiceCollection AddServices(this IServiceCollection services)
    {
        services
            .AddScoped<AService>()
            .AddScoped<BService>()
            .AddScoped<CService>()
            .AddScoped<DService>();

        return services;
    }
}

Além disso, também temos outra biblioteca que inclui alguns repositórios que estão sendo utilizados por estes serviços, então vamos fazer o mesmo.

/// <summary>
/// IServiceCollectionServicesExtensions class
/// </summary>
public static class IServiceCollectionServicesExtensions
{
    /// <summary>
    /// AddCoreServices
    /// </summary>
    /// <param cref="IServiceCollection" name="services">Parameter for <see cref="IServiceCollection"/></param>
    /// <returns>An object of type <see cref="IServiceCollection"/></returns>
    public static IServiceCollection AddRepositories(this IServiceCollection services)
    {
        services
            .AddScoped<ARepository>()
            .AddScoped<BRepository>();

        return services;
    }
}

Agora, temos nossos repositórios e métodos de serviços para injetar criados, mas como os usamos?

Vamos voltar ao nosso Program.cs e adicionar o seguinte:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

// Repositories
builder.Services.AddRepositories(); // 👀

// Services
builder.Services.AddServices(); // 👀

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Isso parece muito mais limpo, não é? Bem, com isso, injetamos com sucesso alguns serviços e repositórios, mas agora parece melhor e na verdade temos o que injetamos na biblioteca externa.