HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Calling common async code from a derived method

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
frommethodasyncderivedcodecallingcommon

Problem

I'm implementing a number of classes in C# that have async methods. However, each of these methods needs to implement some boilerplate code that is common to all. Therefore I've implemented the common code in an async method of a base class; the async methods on the derived classes then call this base class method.

Here's the base class, containing the method that does the common stuff (GetResultAsync).

namespace Redacted
{
    abstract class RepositoryBase : IRepository
    {
        protected RepositoryBase(IRepositoryConfiguration configuration)
        {
            Configuration = configuration;
        }

        protected IRepositoryConfiguration Configuration { get; private set; }

        protected FleetContext CreateDatabaseContext()
        {
            return new FleetContext(Configuration.DatabaseConnectionString);
        }

        protected async Task> GetResultAsync(
            IApiCallerContext context,
            Func> getTask)
        {
            using (new SynchronizationContextChange())
            using (FleetContext db = CreateDatabaseContext())
            {
                bool isSystemOnline = await db.IsSystemOnlineAsync();
                if (!isSystemOnline)
                {
                    return ImmutableApiResult.Offline;
                }

                bool isValidSession = await db.IsValidSessionAsync(context.Caller);
                if (!isValidSession)
                {
                    return ImmutableApiResult.Blocked;
                }

                Task task = getTask(db, context.CancellationToken);
                TValue value = await task;

                return ImmutableApiResult.Create(value);
            }
        }
    }
}


Basically, I have an Entity Framework database context (FleetContext) that exists for the duration of the call. I then perform some common DB-related tasks by calling custom async methods that have been added to the context class. Depending on the result of these cal

Solution

In your code you create 2 boolean variables for a simple if statement conditional, personally I think that you shouldn't create these variables unless you are going to use them in more than one place or for complex condition statements.

using (FleetContext db = CreateDatabaseContext())
        {
            bool isSystemOnline = await db.IsSystemOnlineAsync();
            if (!isSystemOnline)
            {
                return ImmutableApiResult.Offline;
            }

            bool isValidSession = await db.IsValidSessionAsync(context.Caller);
            if (!isValidSession)
            {
                return ImmutableApiResult.Blocked;
            }

            Task task = getTask(db, context.CancellationToken);
            TValue value = await task;

            return ImmutableApiResult.Create(value);
        }


You can also avoid creating the Task variable at the end as well and just create the value.

using (FleetContext db = CreateDatabaseContext())
{
    if (!(await db.IsSystemOnlineAsync()))
    {
        return ImmutableApiResult.Offline;
    }
    else if (!(await db.IsValidSessionAsync(context.Caller)))
    {
        return ImmutableApiResult.Blocked;
    }

    TValue value = await (getTask(db, context.CancellationToken));

    return ImmutableApiResult.Create(value);
}


This shortens the code a little bit and gets straight to the point. Nothing really wrong with the way that you did it, and I haven't really done anything different here either, I just...well... golfed it a bit I guess. I just didn't think we needed to create all those variables

Code Snippets

using (FleetContext db = CreateDatabaseContext())
        {
            bool isSystemOnline = await db.IsSystemOnlineAsync();
            if (!isSystemOnline)
            {
                return ImmutableApiResult<TValue>.Offline;
            }

            bool isValidSession = await db.IsValidSessionAsync(context.Caller);
            if (!isValidSession)
            {
                return ImmutableApiResult<TValue>.Blocked;
            }

            Task<TValue> task = getTask(db, context.CancellationToken);
            TValue value = await task;

            return ImmutableApiResult.Create<TValue>(value);
        }
using (FleetContext db = CreateDatabaseContext())
{
    if (!(await db.IsSystemOnlineAsync()))
    {
        return ImmutableApiResult<TValue>.Offline;
    }
    else if (!(await db.IsValidSessionAsync(context.Caller)))
    {
        return ImmutableApiResult<TValue>.Blocked;
    }

    TValue value = await (getTask(db, context.CancellationToken));

    return ImmutableApiResult.Create<TValue>(value);
}

Context

StackExchange Code Review Q#84349, answer score: 3

Revisions (0)

No revisions yet.