r3plica
r3plica

Reputation: 13397

c# Generic method with async delegate

I have created this generic method:

/// <summary>
/// Executes a list of items
/// </summary>
/// <param name="procedureName">The name of the procedure</param>
/// <param name="parameters">List of oracle parameters</param>
/// <param name="limit">The limit of the results to return</param>
/// <param name="mapper">The oracle mapper method</param>
/// <returns></returns>
protected async Task<IEnumerable<T>> ListAsync<T>(string procedureName, IList<OracleParameter> parameters, int limit, Func<IDataReader, T> mapper)
{
    // Create our list
    var models = new List<T>();
    var counter = 0;

    // Get our reader and return our model
    using (var reader = await _oracleUnitOfWork.ExecuteReaderAsync(procedureName, parameters))
    {
        // While we have rows and our counter 
        while (reader.Read() && ((counter < limit || limit == 0) || limit == 0))
        {
            // If we have a limit, increase our counter (this is first to stop 0 based index messing the amount of objects to return)
            if (limit > 0)
                counter++;

            // Get our item from the database
            models.Add(mapper(reader));
        }
    }

    // Return our list
    return models;
}

Which I can invoke like this:

return await ListAsync("IBPA_MANFCOMPLAINT.complaintSearch", parameters, yield, OracleMapper.Complaint.Map);

But I want to extend this a little. The Mapper just uses the IDataReader to assign the column values to the model properties. For stock instead of using this:

return await ListAsync("ibpa_stock.readRelatedLotstoLot", parameters, 0, OracleMapper.Stock.Map);

I want to do a get request, a bit like this:

return await ListAsync("ibpa_stock.readRelatedLotstoLot", parameters, 0, async (reader) => await GetAsync(reader["lotno"].ToString()));

What can I do to keep things DRY, but at the same time to allow that invocation?

Upvotes: 1

Views: 452

Answers (1)

Servy
Servy

Reputation: 203847

You'll need to have two overloads of the method, one that accepts a Func<IDataReader, T>, and one that accepts a Func<IDataReader, Task<T>>. The second one will need to await the method call when it invokes it, the former won't.

Upvotes: 1

Related Questions