0

I am planning to do an async/await in C# Blazor class constructor method. Although this is written in Blazor it's a generic for C# so it doesn't matter.

public class DoctorsService : IDoctorsService
{
   private readonly IConfiguration _config;

   public DoctorsService(IConfiguration config, IClinicsDoctorsService clinicsDoctorsService)
   {
        _config = config;
        clinicsDoctorsService.GetClinicsDoctorsListAsync(new Dictionary<string, string>());
   }
}

If you noticed the clinicsDoctorsService isn't awaited using await, that's bc the compiler will complain that the method must be in async Task. If I write it like public async Task DoctorsService(), the compiler will complain with another issue because you cannot name a method same with the class name.

user3856437
  • 2,071
  • 4
  • 22
  • 27
  • 2
    In short: No, you can't create an async ctor. Ctor's main purpose is to allocate memory and give some initial value to its fields to set up a valid state for itself. If your object instance relies on some external data then you should consider to have a ctor and async init function. You may wrap these two calls into a factory method which can be async as well. – Peter Csala Dec 10 '20 at 07:04
  • 1
    Does this answer your question? [Can constructors be async?](https://stackoverflow.com/questions/8145479/can-constructors-be-async) – Peter Csala Dec 10 '20 at 07:06
  • Yeah I think it answered my question. Although I still don't know how to create that async init function, that would be another topic to talk about. If someone can point me to a topic about that, it would be so much appreciated. – user3856437 Dec 10 '20 at 07:12

1 Answers1

2

Sync ctor + async Init

public class DoctorsService : IDoctorsService
{
    private readonly IConfiguration _config;
    private readonly IClinicsDoctorsService _clinicsDoctorsService;
    private bool _isInitialized = false;

    internal DoctorsService(IConfiguration config, IClinicsDoctorsService clinicsDoctorsService)
    {
        _config = config;
        _clinicsDoctorsService = clinicsDoctorsService;
        //Set only those fields which are NOT depending on external data 
    }

    internal async Task Init()
    {
        _clinicsDoctorsService.GetClinicsDoctorsListAsync(new Dictionary<string, string>());
        _isInitialized = true;
        //Set those fields which are depending on external data
    }

    public void SomeMethod()
    {
        if (!_isInitialized) 
            throw new NotSupportedException("Please call Init before you call any other instance method.");
        //Some business logic goes here
    }
}

Please note the internal access modifiers.

Dummy factory method

public static class DoctorServiceFactory
{
    public static async Task<IDoctorsService> CreateDoctorsService(IConfiguration config, IClinicsDoctorsService clinicsDoctorsService)
    {
        IDoctorsService svc = new DoctorsService(config, clinicsDoctorsService);
        await svc.Init();
        return svc;
    }
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75