using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.DependencyInjection; namespace Prise { public static class PluginLoadContextExtensions { public static PluginLoadContext AddHostServices(this PluginLoadContext pluginLoadContext, IServiceCollection hostServices, IEnumerable includeTypes = null, IEnumerable excludeTypes = null) { if (includeTypes == null || !includeTypes.Any()) return pluginLoadContext; // short circuit var hostTypes = new List(); var priseServices = hostServices.Where(s => IsPriseService(s.ServiceType)); var includeServices = hostServices.Where(s => Includes(s.ServiceType, includeTypes)); var excludeServices = hostServices.Where(s => Excludes(s.ServiceType, excludeTypes)); foreach (var hostService in hostServices .Except(priseServices) .Union(includeServices) .Except(excludeServices)) pluginLoadContext.AddHostService(hostService); return pluginLoadContext; } public static PluginLoadContext AddHostService(this PluginLoadContext pluginLoadContext, Type hostServiceType, Type hostServiceImplementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { return pluginLoadContext.AddHostService(new ServiceDescriptor(hostServiceType, hostServiceImplementationType, serviceLifetime)); } public static PluginLoadContext AddHostService(this PluginLoadContext pluginLoadContext, T implementation, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { return pluginLoadContext.AddHostService(new ServiceDescriptor(typeof(T), (s) => implementation, serviceLifetime)); } public static PluginLoadContext AddHostService(this PluginLoadContext pluginLoadContext, ServiceDescriptor hostService) { // Add the Host service to the servicecollection of the plugin pluginLoadContext.HostServices.Add(hostService); return pluginLoadContext // A host type will always live inside the host .AddHostTypes(new[] { hostService.ServiceType }) // The implementation type will always exist on the Host, since it will be created here .AddHostTypes(new[] { hostService.ImplementationType ?? hostService.ImplementationInstance?.GetType() ?? hostService.ImplementationFactory?.Method.ReturnType }); } public static PluginLoadContext AddHostTypes(this PluginLoadContext pluginLoadContext, IEnumerable hostTypes) { if (hostTypes == null || !hostTypes.Any()) return pluginLoadContext; // short circuit pluginLoadContext.HostTypes = new List(pluginLoadContext.HostTypes.Union(hostTypes)); return pluginLoadContext; } public static PluginLoadContext AddHostAssemblies(this PluginLoadContext pluginLoadContext, IEnumerable assemblies) { if (assemblies == null || !assemblies.Any()) return pluginLoadContext; // short circuit pluginLoadContext.HostAssemblies = new List(pluginLoadContext.HostAssemblies.Union(assemblies)); return pluginLoadContext; } public static PluginLoadContext AddRemoteTypes(this PluginLoadContext pluginLoadContext, IEnumerable remoteTypes) { if (remoteTypes == null || !remoteTypes.Any()) return pluginLoadContext; // short circuit pluginLoadContext.RemoteTypes = new List(pluginLoadContext.RemoteTypes.Union(remoteTypes)); return pluginLoadContext; } public static PluginLoadContext AddDowngradableHostTypes(this PluginLoadContext pluginLoadContext, IEnumerable downgradableHostTypes) { if (downgradableHostTypes == null || !downgradableHostTypes.Any()) return pluginLoadContext; // short circuit pluginLoadContext.DowngradableHostTypes = new List(pluginLoadContext.DowngradableHostTypes.Union(downgradableHostTypes)); return pluginLoadContext; } public static PluginLoadContext AddDowngradableHostAssemblies(this PluginLoadContext pluginLoadContext, IEnumerable assemblies) { if (assemblies == null || !assemblies.Any()) return pluginLoadContext; // short circuit pluginLoadContext.DowngradableHostAssemblies = new List(pluginLoadContext.DowngradableHostAssemblies.Union(assemblies)); return pluginLoadContext; } public static PluginLoadContext AddAdditionalProbingPaths(this PluginLoadContext pluginLoadContext, IEnumerable additionalProbingPaths) { if (additionalProbingPaths == null || !additionalProbingPaths.Any()) return pluginLoadContext; // short circuit pluginLoadContext.AdditionalProbingPaths = new List(pluginLoadContext.AdditionalProbingPaths.Union(additionalProbingPaths)); return pluginLoadContext; } public static PluginLoadContext SetNativeDependencyLoadPreference(this PluginLoadContext pluginLoadContext, NativeDependencyLoadPreference nativeDependencyLoadPreference) { pluginLoadContext.NativeDependencyLoadPreference = nativeDependencyLoadPreference; return pluginLoadContext; } public static PluginLoadContext SetPlatformVersion(this PluginLoadContext pluginLoadContext, PluginPlatformVersion pluginPlatformVersion) { pluginLoadContext.PluginPlatformVersion = pluginPlatformVersion; return pluginLoadContext; } public static PluginLoadContext SetRuntimePlatformContext(this PluginLoadContext pluginLoadContext, IRuntimePlatformContext runtimePlatformContext) { pluginLoadContext.RuntimePlatformContext = runtimePlatformContext; return pluginLoadContext; } private static bool IsPriseService(Type type) => type.Namespace.StartsWith("Prise."); private static bool Includes(Type type, IEnumerable includeTypes) { if (includeTypes == null) return true; return includeTypes.Contains(type); } private static bool Excludes(Type type, IEnumerable excludeTypes) { if (excludeTypes == null) return false; return excludeTypes.Contains(type); } } }