1

I have a service that I'm adding to my DI container simply using services.AddSingleton<MyService>.

This service requires a static array of strings, which I'm fetching from S3 using an external method LoadStringArrayAsync. This method will be called once for the lifetime of the application and the array will be saved in memory so the other methods in the service can utiliz eit. However, I'm not sure where to call this method.

The constructor is not an option since it doesn't make sense and you can't call async methods from it.

I thought about creating a method that will return the string array either IMemoryCache or fetch it and then cache it, something like so:

private async Task<IEnumerable<string>> GetStringArrayAsync()
{
    return _memoryCache.GetOrCreateAsync("stringArray", async factory => 
    { 
          // Code to fetch string array from S3.
    }
}

But there must be a simpler way more logical way to just call this method and save it into a private member.

Ideas are welcomed.

Gilbert Williams
  • 970
  • 2
  • 10
  • 24
  • 1
    Why doesn't constructor make sense? You can call `GetOrCreate` (without `Async`) so you can initialize it. Your service is created only once (singleton lifetime) and difference between sync and async will be minimal. Or if constructor really does not fit your needs you can have separate method (not async) getting this data and add service to DI using factory. – Roman May 23 '22 at 10:55
  • 1
    @RomanDoskoch Because it doesn't make sense to include a code to download a file from S3 in a constructor, but anyways all the S3 methods to get the file's stream or download it are async anyway... Can you give an example of using factory with async code? – Gilbert Williams May 23 '22 at 10:56
  • 3
    Maybe do something like `ISupportInitialize` that services optionally **implement** and _that whatever is responsible for setting-up the container, **queries-for and invokes.**_ –  May 23 '22 at 11:07
  • @MickyD What about `AsyncLazy`? – Gilbert Williams May 23 '22 at 11:35
  • _"What about AsyncLazy"_ - isn't that generally for lazy _members_ rather than _an entire class object?_ –  May 23 '22 at 11:49
  • Duplicate? https://stackoverflow.com/questions/45924027/avoiding-all-di-antipatterns-for-types-requiring-asynchronous-initialization – Steven May 23 '22 at 12:53
  • Questions: 1. Does this logic need to run upon startup, or is it okay for initialization to execute on first use? 2. What should happen when initialization fails? Should the application prevent from starting, or should just the request fail, and should initialization be tried again? 3. may duplicate (parallel) calls to S3 happen for this initialization, or must there guaranteed be just on (succeeding) initialization call to S3? – Steven May 23 '22 at 13:04
  • @GilbertWilliams btw, I wasn't aware there was an async version of `Lazy<>`. _I learnt something new today_. :) –  May 24 '22 at 02:40

0 Answers0