Skip to content

A framework to simplify application creation by improving dependency injection, validation, config and database handling

License

Notifications You must be signed in to change notification settings

Takasaki-Studio/Lina

Repository files navigation

Lina

A framework to simplify application creation by improving dependency injection, validation, config and database handling

Quality Gate Status

Features

  • Config
    • Easy load
    • Auto inject
  • Database
    • Auto inject
    • Auto import configuration
    • Easy configuration
  • Validation
    • Fluent api
    • Reliable library
    • Easy usage
    • CPF and CNPJ validators
  • Dependency Injection
    • Life time configurable
    • Easy manipulation
    • Services, Repositories, HttpClient and more types of preconfigured dependencies
  • Asp Net Core
    • Blazor render component in controller
    • Clear hosted lifecycle
    • File version provider

Example simple usage

using Config.Net;
using TakasakiStudio.Lina.AutoDependencyInjection;
using TakasakiStudio.Lina.AutoDependencyInjection.Attributes;
using TakasakiStudio.Lina.Utils.LoaderConfig;
using Microsoft.Extensions.DependencyInjection;

var serviceCollection = new ServiceCollection();

serviceCollection.AddLoaderConfig<IAppConfig>();
serviceCollection.AddAutoDependencyInjection<Program>();

var services = serviceCollection.BuildServiceProvider();

services.GetRequiredService<IFooService>().PrintAppName();

public interface IFooService 
{
    public void PrintAppName();
}

[Service<IFooService>]
public class FooService : IFooService
{
    private readonly IAppConfig _appConfig;
    
    public FooService(IAppConfig appConfig)
    {
        _appConfig = appConfig;
    }
    
    public void PrintAppName()
    {
        Console.WriteLine(_appConfig.AppName);
    }
}

public interface IAppConfig 
{
    [Option(DefaultValue = "Test")]
    public string AppName { get; }
}

Config example usage

using Config.Net;
using TakasakiStudio.Lina.Utils.LoaderConfig;
using Microsoft.Extensions.DependencyInjection;

var serviceCollection = new ServiceCollection();

var config = serviceCollection.AddLoaderConfig<IAppConfig>();

Console.WriteLine(config.AppName); // instant use

var services = serviceCollection.BuildServiceProvider();

Console.WriteLine(services.GetRequiredService<IAppConfig>().AppName); // DI usage

public interface IAppConfig 
{
    [Option(DefaultValue = "Test")]
    public string AppName { get; }
}

Database example usage

using Config.Net;
using TakasakiStudio.Lina.Database;
using TakasakiStudio.Lina.Database.Models;
using TakasakiStudio.Lina.Utils.LoaderConfig;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.DependencyInjection;

var serviceCollection = new ServiceCollection();

var config = serviceCollection.AddLoaderConfig<IAppConfig>();
serviceCollection.AddLinaDbContext<Program>((builder, assembly) =>
    builder.UseMySql(config.DatabaseUrl, ServerVersion.AutoDetect(config.DatabaseUrl),
        optionsBuilder => optionsBuilder.MigrationsAssembly(assembly)));

public interface IAppConfig 
{
    [Option(DefaultValue = "Server=localhost;Database=test;User Id=root;Password=root;")]
    public string DatabaseUrl { get; }
}

public class User : BaseEntity<int>
{
    public string Name { get; set; } = string.Empty;
}

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).IsRequired();
    }
}

Validation example usage

using FluentValidation;
using TakasakiStudio.Lina.Common;
using TakasakiStudio.Lina.Common.Extensions;
using TakasakiStudio.Lina.Database.Models;

var user = new User()
{
    Name = "",
    Cpf = "",
    Cnpj = "",
};

if (!await user.IsValid())
{
    Console.WriteLine("invalid");
}

user.Name = "Foo";
user.Cpf = "349.306.930-80";
user.Cnpj = "82.099.001/0001-08";

await user.Validate();

Console.WriteLine("Valid");

public class User : BaseValidated<User>
{
    public required string Name { get; set; }
    public required string Cpf { get; set; }
    public required string Cnpj { get; set; }
    
    protected override void SetupValidator(LinaAbstractValidator<User> rules)
    {
        rules.RuleFor(x => x.Name).NotEmpty();
        rules.RuleFor(x => x.Cpf).ValidCpf();
        rules.RuleFor(x => x.Cnpj).ValidCnpj();
    }
}

Dependency injection example usage

using Config.Net;
using FluentValidation;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.DependencyInjection;
using TakasakiStudio.Lina.AutoDependencyInjection;
using TakasakiStudio.Lina.AutoDependencyInjection.Attributes;
using TakasakiStudio.Lina.Common;
using TakasakiStudio.Lina.Database;
using TakasakiStudio.Lina.Database.Interfaces;
using TakasakiStudio.Lina.Database.Models;
using TakasakiStudio.Lina.Database.Repositories;
using TakasakiStudio.Lina.Utils.LoaderConfig;

var serviceCollection = new ServiceCollection();

var config = serviceCollection.AddLoaderConfig<IAppConfig>();
serviceCollection.AddAutoDependencyInjection<Program>();
serviceCollection.AddLinaDbContext<Program>((builder, assembly) =>
    builder.UseMySql(config.DatabaseUrl, ServerVersion.AutoDetect(config.DatabaseUrl),
        optionsBuilder => optionsBuilder.MigrationsAssembly(assembly)));

public interface IAppConfig
{
    [Option(DefaultValue = "Server=localhost;Database=test;User Id=root;Password=root;")]
    public string DatabaseUrl { get; }
}

public class User : BaseValidatedEntity<User, int>
{
    public string Name { get; set; } = string.Empty;
    
    protected override void SetupValidator(LinaAbstractValidator<ExampleModel> rules)
    {
        rules.RuleFor(x => x.Name).NotEmpty();
    }

    public static implicit operator User(UserViewModel viewModel)
    {
        return new User
        {
            Name = viewModel.Name
        };
    }

    public static implicit operator UserViewModel(User user)
    {
        return new UserViewModel
        {
            Name = user.Name
        };
    }
}

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).IsRequired();
    }
}

public record UserViewModel
{
    public string Name { get; set; } = string.Empty;
}

public interface IUserRepository : IBaseRepository<User, int>
{
}

[Repository<IUserRepository>]
public class UserRepository : BaseRepository<User, int>, IUserRepository
{
    public UserRepository(DbContext dbContext) : base(dbContext)
    {
    }
}

public interface IUserService
{
}

[Service<IUserService>]
public class UserService : IUserService
{
    private readonly IUserRepository _userRepository;

    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public async Task<UserViewModel?> Add(UserViewModel userViewModel)
    {
        User user = userViewModel;
        await user.Validate();

        await _userRepository.Add(user);
        await _userRepository.Commit();

        return user;
    }
}

Blazor components

using Microsoft.AspNetCore.Mvc;
using TakasakiStudio.Lina.AspNet.Controllers;

[Controller]
public class AuthController() : PageController
{
    [HttpGet]
    public IActionResult Login()
    {
        return RenderComponent<LoginPage>(); // LoginPage is a Blazor component
    }
}

Clear hosted lifecycle

using TakasakiStudio.Lina.AspNet.Workers;

public class MyWorker : AbstractHostedLifecycleService
{
    public override Task StartingAsync(CancellationToken cancellationToken)
    {
        /*...*/
    }
}

Libraries usage

License

The entire project, except for the file FileVersionProvider.cs is licensed under the The Unlicense license. The file FileVersionProvider.cs was copied from Asp.NET Core under the MIT License.