Skip to content

Integration

Overview

This section explains how to integrate the TinyResult library with other libraries and frameworks.

ASP.NET Core Integration

Controller Integration

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IUserService _userService;

    public UsersController(IUserService userService)
    {
        _userService = userService;
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetUser(int id)
    {
        var result = await _userService.GetUserAsync(id);
        return result.Match(
            user => Ok(user),
            error => error.Code switch
            {
                ErrorCode.NotFound => NotFound(error.Message),
                _ => StatusCode(500, error.Message)
            }
        );
    }
}

Middleware Integration

public class ResultMiddleware
{
    private readonly RequestDelegate _next;

    public ResultMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            var error = Error.FromException(ex);
            context.Response.StatusCode = GetStatusCode(error.Code);
            await context.Response.WriteAsJsonAsync(new { error.Message });
        }
    }

    private static int GetStatusCode(ErrorCode code) => code switch
    {
        ErrorCode.NotFound => 404,
        ErrorCode.ValidationError => 400,
        _ => 500
    };
}

Entity Framework Core Integration

Repository Pattern

public class UserRepository : IUserRepository
{
    private readonly DbContext _context;

    public UserRepository(DbContext context)
    {
        _context = context;
    }

    public async Task<Result<User>> GetUserAsync(int id)
    {
        return await Result<User>.TryAsync(async () =>
        {
            var user = await _context.Users.FindAsync(id);
            if (user == null)
                return Result<User>.Failure(ErrorCode.NotFound, "User not found");
            return Result<User>.Success(user);
        });
    }
}

Unit of Work Pattern

public class UnitOfWork : IUnitOfWork
{
    private readonly DbContext _context;

    public UnitOfWork(DbContext context)
    {
        _context = context;
    }

    public async Task<Result<int>> SaveChangesAsync()
    {
        return await Result<int>.TryAsync(async () =>
        {
            var changes = await _context.SaveChangesAsync();
            return Result<int>.Success(changes);
        });
    }
}

MediatR Integration

Command Handler

public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, Result<User>>
{
    private readonly IUserRepository _repository;
    private readonly IUserValidator _validator;

    public CreateUserCommandHandler(IUserRepository repository, IUserValidator validator)
    {
        _repository = repository;
        _validator = validator;
    }

    public async Task<Result<User>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        var validationResult = _validator.Validate(request.User);
        if (!validationResult.IsValid)
            return Result<User>.Failure(validationResult.Errors);

        return await _repository.CreateUserAsync(request.User);
    }
}

Query Handler

public class GetUserQueryHandler : IRequestHandler<GetUserQuery, Result<User>>
{
    private readonly IUserRepository _repository;

    public GetUserQueryHandler(IUserRepository repository)
    {
        _repository = repository;
    }

    public async Task<Result<User>> Handle(GetUserQuery request, CancellationToken cancellationToken)
    {
        return await _repository.GetUserAsync(request.UserId);
    }
}

AutoMapper Integration

Profile Definition

public class UserProfile : Profile
{
    public UserProfile()
    {
        CreateMap<User, UserDto>();
        CreateMap<CreateUserDto, User>();
    }
}

Service Usage

public class UserService : IUserService
{
    private readonly IUserRepository _repository;
    private readonly IMapper _mapper;

    public UserService(IUserRepository repository, IMapper mapper)
    {
        _repository = repository;
        _mapper = mapper;
    }

    public async Task<Result<UserDto>> GetUserAsync(int id)
    {
        return await _repository.GetUserAsync(id)
            .MapAsync(user => _mapper.Map<UserDto>(user));
    }
}

FluentValidation Integration

Validator Definition

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Name).NotEmpty();
        RuleFor(x => x.Email).EmailAddress();
    }
}

Service Usage

public class UserService : IUserService
{
    private readonly IUserRepository _repository;
    private readonly IValidator<User> _validator;

    public UserService(IUserRepository repository, IValidator<User> validator)
    {
        _repository = repository;
        _validator = validator;
    }

    public async Task<Result<User>> CreateUserAsync(User user)
    {
        var validationResult = await _validator.ValidateAsync(user);
        if (!validationResult.IsValid)
        {
            var errors = validationResult.Errors
                .ToDictionary(e => e.PropertyName, e => e.ErrorMessage);
            return Result<User>.Failure(ErrorCode.ValidationError, "Validation failed", errors);
        }

        return await _repository.CreateUserAsync(user);
    }
}

Serilog Integration

Logger Definition

public static class ResultLogger
{
    private static readonly ILogger Log = Serilog.Log.ForContext<ResultLogger>();

    public static void LogResult<T>(Result<T> result)
    {
        if (result.IsSuccess)
            Log.Information("Operation succeeded: {Value}", result.Value);
        else
            Log.Error("Operation failed: {Error}", result.Error);
    }
}

Service Usage

public class UserService : IUserService
{
    private readonly IUserRepository _repository;

    public UserService(IUserRepository repository)
    {
        _repository = repository;
    }

    public async Task<Result<User>> GetUserAsync(int id)
    {
        var result = await _repository.GetUserAsync(id);
        ResultLogger.LogResult(result);
        return result;
    }
}

Next Steps