C
C#15mo ago
pirrippu

❔ Strategy for plugin architecture dependency injection

I am creating an application with simple plugins in which registration information of plugins are stored in a database. I am having challenges with dependency injection. Each plugin assembly has the following marker assembly:
csharp
public interface IPluginRegistrar
{
IServiceCollection RegisterPluginServices(IServiceCollection services);
}
csharp
public interface IPluginRegistrar
{
IServiceCollection RegisterPluginServices(IServiceCollection services);
}
Idea is to call the interface above for each of plugin assemblies stored in the database, but I cannot resolve my plugin DbContext without doing BuildServiceProvider() which I cannot do(or not advised to do) during ConfigureServices(). Is there any strategy or pattern to tackle this?
12 Replies
JakenVeina
JakenVeina15mo ago
as in, you need a DbContext to retrieve the info needed to load the plugins?
pirrippu
pirrippu15mo ago
Yes exactly like that, and then register services required by the plugins
JakenVeina
JakenVeina15mo ago
so, you need a DbContext before your main application IoC container exists so, you can't use the main application IoC container so, you need to create one yourself or create a setup-only IoC container which, BTW, is already a thing
pirrippu
pirrippu15mo ago
What do you mean, setup-only IoC container? I make an intermediary ServiceProvider, like a child container?
JakenVeina
JakenVeina15mo ago
not sure what you mean by child container but intermediary, sure logically speaking...
var applicationServices = new ServiceCollection();

using(var setupServiceProvider = new ServiceCollection().ConfigureSetup().BuildServiceProvider())
applicationServices.ConfigureSetup(setupServiceProvider);

using var applicationServiceProvider = applicationServices.BuildServiceProvider();

applicationServiceProvider
.GetRequiredService<EntryPoint>()
.Run();
var applicationServices = new ServiceCollection();

using(var setupServiceProvider = new ServiceCollection().ConfigureSetup().BuildServiceProvider())
applicationServices.ConfigureSetup(setupServiceProvider);

using var applicationServiceProvider = applicationServices.BuildServiceProvider();

applicationServiceProvider
.GetRequiredService<EntryPoint>()
.Run();
ASP.NET already provides exactly this setup
pirrippu
pirrippu15mo ago
Interesting approach, thanks. That will take care of possible singleton registrations, right? since setupServiceProvider is disposed.
JakenVeina
JakenVeina15mo ago
yup you can definitely register all the same stuff for setup that you do for the main app
pirrippu
pirrippu15mo ago
holy schomkes, hol 'up I forgot ServiceProvider can be disposed I'll test this one out tomorrow, maybe I just need to sleep on this
JakenVeina
JakenVeina15mo ago
arguably shouldn't but definitely can this is how ASP.NET handles configuration IConfiguration instances need to be available during service configuration as well as a bunch of other setup stuff that's the difference between ConfigureHostServices() and ConfigureApplicationServices() scratch that ConfigureHostConfiguration() versus ConfigureAppConfiguration() so, nevermind, ASP.NET doesn't do this already it does something very similar, but for configuration doesn't actually build a full IoC for setup, just a separate ConfigurationBuilder() and IConfiguration conceptually, it's about the same thing, and you can do what I wrote above
pirrippu
pirrippu15mo ago
I see, thank you! But what you said above makes a good point, I'll do something similar. Won't hurt me if I make an intermediate and separate IServiceCollection for DbContext and other IOptions I need for plugin configuration
JakenVeina
JakenVeina15mo ago
yup
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.