Chacha
Chacha

Reputation: 63

How to use class immediately before injection?

I have some data in sql that need to initial before BuildWebHost. Like this

public static void PrepareToken(this IServiceCollection services)
{
    services.AddSingleton<IValidationToken, ValidationToken>();
    //need to use ValidationToken to init data immediately.

    //services.Add...  Other class
}

I can write another class to do it. but I want to reuse ValidationToken. I can't just new ValidationToken, Because the ValidationToken constructor like that:

private readonly ICacheManager _cacheManager;
private readonly IXXXXXRepository _XXXXXXXRepository;

private Dictionary<string, string> _validationToken = null;
private readonly object _lockObject = new object();

public ValidationToken(IXXXXXXXRepository XXXXXXXXRepository, ICacheManager cacheManager)
{
    _XXXXXXXRepository = XXXXXXXXRepository;
    _cacheManager = cacheManager;
}

Anyone has any pattern or idea to solve this problem?

Upvotes: 0

Views: 84

Answers (1)

poke
poke

Reputation: 388153

You cannot do that right after services.Add~ because at that time, none of the services exist yet. The service collection only collects service registrations. It’s only later that the service collection is built into a service provider at which point you can resolve these services.

If you need to initialize this ValidationToken, then you should do that within its own constructor. That way, you can make sure that anything that depends on it will get an intialized token.

Alternatively, if you require the validation token to initialize other services, then you should make those services depend on the token properly and also have them initialize in their respective constructors.


If you need to initialize something before your web application starts, then do after building the web host but before starting the host. So your Program.Main may look like this:

public static void Main(string[] args)
{
    // create and build the host to make the DI container available
    var host = CreateHostBuilder(args).Build();

    // create a DI service scope in which the initialization can be done
    using (var scope = host.Services.CreateScope())
    {
        // retrieve service and initialize whatever
        var token = scope.ServiceProvider.GetService<ValidationToken>();
        token.Initialize();
    }

    // start the host which spins up e.g. the ASP.NET Core web application
    host.Run();
}

This uses the generic HostBuilder from .NET Core 3.x. If you are still using the WebHostBuilder, then this will almost look identical to that; just operate on the returned WebHost instead.

Upvotes: 1

Related Questions