ubeac / ubeac-api

Source of uBeac .NET Core packages
3 stars 2 forks source link

Stop Calling Build Service Provider #161

Open ilhesam opened 1 year ago

ilhesam commented 1 year ago

Calling BuilderServiceProvider method of IServiceCollection is a bad practice. In some projects we have it, We should implement the alternative solutions and remove calling BuildServiceProvider.

ilhesam commented 1 year ago
Identity\uBeac.Core.Identity\Extensions\RoleExtensions.cs(41)
Identity\uBeac.Core.Identity\Extensions\RoleExtensions.cs(65)
Identity\uBeac.Core.Identity\Extensions\RoleExtensions.cs(81)
Identity\uBeac.Core.Identity\Extensions\RoleExtensions.cs(96)
Identity\uBeac.Core.Identity\Extensions\UnitExtensions.cs(35)
Identity\uBeac.Core.Identity\Extensions\UnitExtensions.cs(52)
Identity\uBeac.Core.Identity\Extensions\UnitExtensions.cs(68)
Identity\uBeac.Core.Identity\Extensions\UnitExtensions.cs(83)
Identity\uBeac.Core.Identity\Extensions\UnitTypeExtensions.cs(35)
Identity\uBeac.Core.Identity\Extensions\UnitTypeExtensions.cs(52)
Identity\uBeac.Core.Identity\Extensions\UnitTypeExtensions.cs(68)
Identity\uBeac.Core.Identity\Extensions\UnitTypeExtensions.cs(83)
Identity\uBeac.Core.Identity\Extensions\UserExtensions.cs(45)
Identity\uBeac.Core.Identity\Extensions\UserExtensions.cs(71)
Identity\uBeac.Core.Identity\Extensions\UserExtensions.cs(120)
Identity\uBeac.Core.Identity\Extensions\UserExtensions.cs(135)
Logging\uBeac.Core.Logging\AppContextEnricher.cs(20)
ilhesam commented 1 year ago

We will have an implementation of IDataSeeder per entity. Look like this:

public interface IDataSeeder
{
    Task SeedAsync(CancellationToken cancellationToken = default);
}
public class UserSeeder<TKey, TUser> : IDataSeeder
    where TKey : IEquatable<TKey>
    where TUser : User<TKey>
{
    private readonly IUserService<TKey, TUser> _userService;
    private readonly IUserRoleService<TKey, TUser> _userRoleService;
    private readonly UserOptions<TKey, TUser> _userOptions;

    public UserSeeder(IUserService<TKey, TUser> userService, IUserRoleService<TKey, TUser> userRoleService, UserOptions<TKey, TUser> userOptions)
    {
        _userService = userService;
        _userRoleService = userRoleService;
        _userOptions = userOptions;
    }

    public async Task SeedAsync(CancellationToken cancellationToken = default)
    {
        // Create Admin User
    }
}

And, we should have an extension method that fetches all implementations of IDataSeeder from IServiceProvider and calls their Seed method:

    public static IApplicationBuilder SeedData(this IApplicationBuilder app)
    {
        var seeders = app.ApplicationServices.CreateScope()
            .ServiceProvider
            .GetServices<IDataSeeder>();

        foreach (var seeder in seeders)
        {
            seeder.SeedAsync().Wait();
        }

        return app;
    }

In Program.cs:

app.SeedData();

In this way, we will no longer need to call BuildServiceProvider and each seeders injects the services it needs.