using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.DependencyInjection; using Prise.Activation; using Prise.AssemblyLoading; using Prise.AssemblyScanning; using Prise.Proxy; namespace Prise.DependencyInjection { public static class ServiceCollectionExtensions { /// /// This bootstrapper adds the basic Prise services as well as the IPluginLoader /// /// The path to the directory to scan for plugins /// A ServiceCollection that has the following types registered and ready for injection: /// , , ,, , and /// public static IServiceCollection AddPrise(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { return services // Add all the factories .AddFactory(DefaultFactories.DefaultAssemblyScanner, serviceLifetime) .AddFactory(DefaultFactories.DefaultPluginTypeSelector, serviceLifetime) .AddFactory(DefaultFactories.DefaultParameterConverter, serviceLifetime) .AddFactory(DefaultFactories.DefaultResultConverter, serviceLifetime) .AddFactory(DefaultFactories.DefaultPluginActivator, serviceLifetime) .AddFactory(DefaultFactories.DefaultAssemblyLoader, serviceLifetime) // Add the loader .AddService(new ServiceDescriptor(typeof(IPluginLoader), typeof(DefaultPluginLoader), serviceLifetime)) ; } /// /// This bootstrapper adds the basic Prise services, the IPluginLoader and support to load Prise NuGet Packages /// /// The path to the directory to scan for plugins /// A ServiceCollection that has the following types registered and ready for injection: /// , , ,, , and /// public static IServiceCollection AddPriseNugetPackages(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { return services // Add all the factories .AddFactory(DefaultFactories.DefaultNuGetAssemblyScanner, serviceLifetime) .AddFactory(DefaultFactories.DefaultPluginTypeSelector, serviceLifetime) .AddFactory(DefaultFactories.DefaultParameterConverter, serviceLifetime) .AddFactory(DefaultFactories.DefaultResultConverter, serviceLifetime) .AddFactory(DefaultFactories.DefaultPluginActivator, serviceLifetime) .AddFactory(DefaultFactories.DefaultAssemblyLoader, serviceLifetime) // Add the loader .AddService(new ServiceDescriptor(typeof(IPluginLoader), typeof(DefaultPluginLoader), serviceLifetime)) ; } /// /// This is the bootstrapper method to register a Plugin of using Prise /// /// The path to start scanning for plugins /// The framework of the host, optional /// If , an is registered, all plugins of this type will have the same configuration. If only the first found Plugin is registered /// A builder function that you can use configure the load context /// The Plugin type /// A full configured ServiceCollection that will resolve or an based on public static IServiceCollection AddPrise(this IServiceCollection services, Func pathToPlugin, Func hostFramework = null, bool allowMultiple = false, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped, Action configureContext = null) where T : class { return services .AddPrise(serviceLifetime) // Adds the default Prise Services .AddService(new ServiceDescriptor(allowMultiple ? typeof(IEnumerable) : typeof(T), (sp) => { var loader = sp.GetRequiredService(); var scanResults = loader.FindPlugins(pathToPlugin.Invoke(sp)).Result; if (!scanResults.Any()) throw new PriseDependencyInjectionException($"No plugin assembly was found for plugin type {typeof(T).Name}"); if (!allowMultiple) // Only 1 plugin is requested return loader.LoadPlugin(scanResults.First(), hostFramework?.Invoke(sp), configureContext).Result; var plugins = new List(); foreach (var scanResult in scanResults) plugins.AddRange(loader.LoadPlugins(scanResult, hostFramework?.Invoke(sp), configureContext).Result); return plugins; }, serviceLifetime)) ; } public static IServiceCollection AddFactory(this IServiceCollection services, Func func, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) where T : class { Func> factoryOfFuncT = (sp) => func; Func factoryOfT = (sp) => sp.GetRequiredService>()() as T; return services .AddService(new ServiceDescriptor(typeof(Func), factoryOfFuncT, serviceLifetime)) .AddService(new ServiceDescriptor(typeof(T), factoryOfT, serviceLifetime)); } private static IServiceCollection AddService(this IServiceCollection services, ServiceDescriptor serviceDescriptor) { services .Add(serviceDescriptor); return services; } } }