Home > Blockchain >  return type According to logic
return type According to logic

Time:11-22

I'm using c# and I'm using CQRS So let's image this scenario

public async Task<Response<SaleProducts>> Handle(CreateSaleProductCommand request, CancellationToken cancellationToken)
            {
                var newEntity = MyCustomerMapper.Mapper.Map<SaleProducts>(request);
                if (newEntity is null)
                    throw new ApplicationException("There is a problem in mapper");

                var itemToReturn = await _repositoryCommand.AddProductToSaleAsync(newEntity);
                if(itemToReturn != null)
                {
                    itemToReturn.Product = await _productQueryRepository.GetByIdAsync(itemToReturn.ProductId);  
                    return new Response<SaleProducts>(itemToReturn);
                }
                else
                    throw new ApplicationException("There is a problem when saving the product");


            }

so this function return Response<SaleProducts> after saving.

Now I like to make some verification in my _repositoryCommand.AddProductToSaleAsync.

So if verification is ok I return SaleProducts if not I return other value(like bool or string) for exepmle.

So is there any way to have something similar to this

 public async Task<Response<SaleProducts | bool>> Handle(CreateSaleProductCommand request, CancellationToken cancellationToken)

return type SaleProducts | bool | string

CodePudding user response:

There is no build-in way to represent that in C# (unless count value tuples as one, but personally I prefer to use it when all elements can be present in the result). You can look into using Either monad from some existing libraries like language-ext:

public async Task<Response<Either<string, SaleProducts>>> Handle()

Or OneOf:

This library provides F# style discriminated unions for C#, using a custom type OneOf<T0, ... Tn>. An instance of this type holds a single value, which is one of the types in its generic argument list.

Which referes the similar problem as one of the common to solve with OneOf:

The most frequent use case is as a return value, when you need to return different results from a method.

public OneOf<User, InvalidName, NameTaken> CreateUser(string username)
{
    if (!IsValid(username)) return new InvalidName();
    var user = _repo.FindByUsername(username);
    if(user != null) return new NameTaken();
    var user = new User(username);
    _repo.Save(user);
    return user;
}

And provides handy methods to work with it.

Or FluentResults:

FluentResults is a lightweight .NET library developed to solve a common problem. It returns an object indicating success or failure of an operation instead of throwing/using exceptions.

CodePudding user response:

I would probably just use a tuple for this:

public async Task<Response<(SaleProducts? Products, string? Status)>> Handle(CreateSaleProductCommand request, CancellationToken cancellationToken)

Then your Handle turns into:

public async Task<Response<SaleProducts>> Handle(CreateSaleProductCommand request, CancellationToken cancellationToken)
            {
                var newEntity = MyCustomerMapper.Mapper.Map<SaleProducts>(request);
                if (newEntity is null)
                    throw new ApplicationException("There is a problem in mapper");

                var (itemToReturn, textStatus) = await _repositoryCommand.AddProductToSaleAsync(newEntity);
                if(itemToReturn != null)
                {
                    itemToReturn.Product = await _productQueryRepository.GetByIdAsync(itemToReturn.ProductId);  
                    return new Response<SaleProducts>(itemToReturn);
                }
                else
                {
                    // Do whatever processing you want to do with textStatus
                    ...
                    throw new ApplicationException("There is a problem when saving the product");
                }


            }
  •  Tags:  
  • c#
  • Related