Skip to content

Instantly share code, notes, and snippets.

@Ilchert
Forked from uhfath/DIPlugins.cs
Created January 12, 2024 09:51
Show Gist options
  • Save Ilchert/6b9a8b09109e9a31dd1783750097bf4c to your computer and use it in GitHub Desktop.
Save Ilchert/6b9a8b09109e9a31dd1783750097bf4c to your computer and use it in GitHub Desktop.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
public class Programm
{
static int _idCounter = 0;
interface IService
{
public int Id { get; }
public void Test(string suffix);
}
class RootService : IService
{
public int Id { get; } = ++_idCounter;
public void Test(string suffix) => Console.WriteLine("{0}ROOT_SERVICE: {1}", suffix, Id);
}
class RootInterfaceService : IService
{
public int Id { get; } = ++_idCounter;
public void Test(string suffix) => Console.WriteLine("{0}ROOT_INTERFACE_SERVICE: {1}", suffix, Id);
}
class RootScopedService : IService
{
public int Id { get; } = ++_idCounter;
public void Test(string suffix) => Console.WriteLine("{0}ROOT_SCOPED_SERVICE: {1}", suffix, Id);
}
class PluginRootOverrideService : IService
{
public int Id { get; } = ++_idCounter;
public void Test(string suffix) => Console.WriteLine("{0}PLUGIN_ROOT_OVERRIDE_SERVICE: {1}", suffix, Id);
}
class PluginScopedService : IService
{
public int Id { get; } = ++_idCounter;
public void Test(string suffix) => Console.WriteLine("{0}PLUGIN_SCOPED_SERVICE: {1}", suffix, Id);
}
interface IPlugin
{
public void Test(string suffix);
}
class App : IDisposable
{
private readonly RootService _rootService;
private readonly IService _rootInterfaceService;
private readonly RootScopedService _rootScopedService;
private readonly ServiceProvider _pluginServiceProvider;
public App(
RootService rootService,
IService rootInterfaceService,
RootScopedService rootScopedService,
IServiceProvider serviceProvider)
{
_rootService = rootService;
_rootInterfaceService = rootInterfaceService;
_rootScopedService = rootScopedService;
_pluginServiceProvider = InitPlugin(PluginImplementation.Name, serviceProvider);
}
public void Test(string suffix)
{
_rootService.Test("HOST -> " + suffix);
_rootInterfaceService.Test("HOST -> " + suffix);
_rootScopedService.Test("HOST -> " + suffix);
using var scope = _pluginServiceProvider.CreateScope();
scope.ServiceProvider.GetRequiredService<IPlugin>().Test("HOST -> ");
}
public void Dispose()
{
_pluginServiceProvider.Dispose();
}
}
class PluginImplementation : IPlugin
{
private readonly IService _pluginOverride;
private readonly PluginScopedService _pluginScopedService;
private readonly RootService _rootService;
private readonly RootScopedService _rootScopedService;
public const string Name = nameof(PluginImplementation);
public static void Configure(ServiceCollection rootServices)
{
rootServices.Configure<PluginRegistration>(Name, o => o.ConfigureServices = static (IServiceProvider sp, ServiceCollection services) =>
{
services.AddSingleton<IService, PluginRootOverrideService>();
services.AddSingleton(_ = sp.GetRequiredService<RootService>());
services.AddSingleton(_ = sp.GetRequiredService<RootScopedService>());
services.AddScoped<IPlugin, PluginImplementation>(); //main plugin service
services.AddScoped<PluginScopedService>(); //scoped service in pluging
});
}
public PluginImplementation(
IService pluginOverride,
PluginScopedService pluginScopedService,
RootService rootService,
RootScopedService rootScopedService)
{
_pluginOverride = pluginOverride;
_pluginScopedService = pluginScopedService;
_rootService = rootService;
_rootScopedService = rootScopedService;
}
public void Test(string suffix)
{
_rootService.Test("PLUGIN -> " + suffix);
_pluginScopedService.Test("PLUGIN -> " + suffix);
_pluginOverride.Test("PLUGIN -> " + suffix);
_rootScopedService.Test("PLUGIN -> " + suffix);
}
}
class PluginRegistration
{
public Action<IServiceProvider, ServiceCollection> ConfigureServices = delegate { };
}
static ServiceProvider InitPlugin(string pluginName, IServiceProvider serviceProvider)
{
var pluginServices = new ServiceCollection();
var pluginRegistration = serviceProvider.GetRequiredService<IOptionsMonitor<PluginRegistration>>().Get(pluginName);
pluginRegistration.ConfigureServices(serviceProvider, pluginServices);
return pluginServices.BuildServiceProvider(new ServiceProviderOptions
{
ValidateOnBuild = true,
ValidateScopes = true,
});
}
public static void Main()
{
var services = new ServiceCollection();
services.AddSingleton<RootService>(); //host's singleton service
services.AddSingleton<IService, RootInterfaceService>(); //same as above but by an interface
services.AddScoped<RootScopedService>(); //host's scoped service
services.AddScoped<App>(); //host's scoped application service
PluginImplementation.Configure(services);
using var rootServiceProvider = services.BuildServiceProvider(new ServiceProviderOptions
{
ValidateOnBuild = true,
ValidateScopes = true,
});
using var rootScope_1 = rootServiceProvider.CreateScope();
rootScope_1.ServiceProvider.GetRequiredService<App>().Test("MAIN #1.1 -> ");
// rootScope_1.ServiceProvider.GetRequiredService<App>().Test("MAIN #1.2 -> ");
//
// using var rootScope_2 = rootServiceProvider.CreateScope();
// rootScope_2.ServiceProvider.GetRequiredService<App>().Test("MAIN #2.1 -> ");
// rootScope_2.ServiceProvider.GetRequiredService<App>().Test("MAIN #2.2 -> ");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment