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;
}
}
}