diff --git a/samples/WebApp/Startup.cs b/samples/WebApp/Startup.cs index 06a9c85..b79fff4 100644 --- a/samples/WebApp/Startup.cs +++ b/samples/WebApp/Startup.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Hosting; using Weikio.PluginFramework.Samples.Shared; using Weikio.PluginFramework.Abstractions; +using Weikio.PluginFramework.AspNetCore; using Weikio.PluginFramework.Catalogs; namespace WebApp diff --git a/samples/WebAppWithAppSettings/Startup.cs b/samples/WebAppWithAppSettings/Startup.cs index ccaef96..eb81fea 100644 --- a/samples/WebAppWithAppSettings/Startup.cs +++ b/samples/WebAppWithAppSettings/Startup.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Weikio.PluginFramework.Catalogs.NuGet; using Weikio.PluginFramework.Samples.Shared; using Weikio.PluginFramework.TypeFinding; @@ -13,7 +14,8 @@ public void ConfigureServices(IServiceCollection services) { TypeFinderOptions.Defaults.TypeFinderCriterias.Add(TypeFinderCriteriaBuilder.Create().Implements().Tag("MathOperator")); TypeFinderOptions.Defaults.TypeFinderCriterias.Add(TypeFinderCriteriaBuilder.Create().Tag("All")); - services.AddPluginFramework(); + services.AddPluginFramework() + .AddNugetConfiguration(); services.AddControllers(); } diff --git a/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj b/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj index 0462758..a60d9ed 100644 --- a/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj +++ b/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj @@ -6,6 +6,7 @@ + diff --git a/samples/WebAppWithDelegate/Startup.cs b/samples/WebAppWithDelegate/Startup.cs index c4c7064..aec5e44 100644 --- a/samples/WebAppWithDelegate/Startup.cs +++ b/samples/WebAppWithDelegate/Startup.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Weikio.PluginFramework.AspNetCore; using Weikio.PluginFramework.Catalogs; using Weikio.PluginFramework.Catalogs.Delegates; @@ -54,6 +55,7 @@ public void ConfigureServices(IServiceCollection services) services.AddPluginFramework() .AddPluginCatalog(new CompositePluginCatalog(actionCatalog, funcCatalog, funcWithExternalServiceCatalog)); + services.AddSingleton(); services.AddControllers(); } diff --git a/samples/WebAppWithNuget/Startup.cs b/samples/WebAppWithNuget/Startup.cs index 7104f50..d94d9df 100644 --- a/samples/WebAppWithNuget/Startup.cs +++ b/samples/WebAppWithNuget/Startup.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Weikio.PluginFramework.AspNetCore; using Weikio.PluginFramework.Catalogs; using Weikio.PluginFramework.Catalogs.NuGet; using Weikio.PluginFramework.Samples.Shared; diff --git a/samples/WebAppWithRoslyn/Startup.cs b/samples/WebAppWithRoslyn/Startup.cs index b83a13a..2720717 100644 --- a/samples/WebAppWithRoslyn/Startup.cs +++ b/samples/WebAppWithRoslyn/Startup.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Weikio.PluginFramework.AspNetCore; using Weikio.PluginFramework.Catalogs; using Weikio.PluginFramework.Catalogs.Roslyn; diff --git a/src/PluginFramework.sln b/src/PluginFramework.sln index 235d067..cf7b875 100644 --- a/src/PluginFramework.sln +++ b/src/PluginFramework.sln @@ -61,11 +61,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsApp", "..\samples\W EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsPluginsLibrary", "..\samples\WinFormsPluginsLibrary\WinFormsPluginsLibrary.csproj", "{E92B0C5D-FFAC-4AB9-B069-869AEED565B0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weikio.PluginFramework.Configuration", "Weikio.PluginFramework.Configuration\Weikio.PluginFramework.Configuration.csproj", "{882BB58E-D256-4BBF-8C5F-80C4FA39B775}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Weikio.PluginFramework.Configuration", "Weikio.PluginFramework.Configuration\Weikio.PluginFramework.Configuration.csproj", "{882BB58E-D256-4BBF-8C5F-80C4FA39B775}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAppWithAppSettings", "..\samples\WebAppWithAppSettings\WebAppWithAppSettings.csproj", "{A5FAE1A5-74A0-4A83-9520-DCABF6610ADE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAppWithAppSettings", "..\samples\WebAppWithAppSettings\WebAppWithAppSettings.csproj", "{A5FAE1A5-74A0-4A83-9520-DCABF6610ADE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAppPluginsLibrary", "..\samples\WebAppPluginsLibrary\WebAppPluginsLibrary.csproj", "{38CCE0F7-F998-4766-A14A-44C047E8D0AA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAppPluginsLibrary", "..\samples\WebAppPluginsLibrary\WebAppPluginsLibrary.csproj", "{38CCE0F7-F998-4766-A14A-44C047E8D0AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weikio.PluginFramework.Abstractions.DependencyInjection", "Weikio.PluginFramework.Abstractions.DependencyInjection\Weikio.PluginFramework.Abstractions.DependencyInjection.csproj", "{64FD5284-87A2-4A6D-8CCD-324CDD944A11}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -185,6 +187,10 @@ Global {38CCE0F7-F998-4766-A14A-44C047E8D0AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {38CCE0F7-F998-4766-A14A-44C047E8D0AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {38CCE0F7-F998-4766-A14A-44C047E8D0AA}.Release|Any CPU.Build.0 = Release|Any CPU + {64FD5284-87A2-4A6D-8CCD-324CDD944A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64FD5284-87A2-4A6D-8CCD-324CDD944A11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64FD5284-87A2-4A6D-8CCD-324CDD944A11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64FD5284-87A2-4A6D-8CCD-324CDD944A11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Weikio.PluginFramework.Abstractions.DependencyInjection/IPluginFrameworkBuilder.cs b/src/Weikio.PluginFramework.Abstractions.DependencyInjection/IPluginFrameworkBuilder.cs new file mode 100644 index 0000000..944c9b5 --- /dev/null +++ b/src/Weikio.PluginFramework.Abstractions.DependencyInjection/IPluginFrameworkBuilder.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; + +namespace Weikio.PluginFramework.Abstractions.DependencyInjection +{ + public interface IPluginFrameworkBuilder + { + IServiceCollection Services { get; } + } +} diff --git a/src/Weikio.PluginFramework.Abstractions.DependencyInjection/Weikio.PluginFramework.Abstractions.DependencyInjection.csproj b/src/Weikio.PluginFramework.Abstractions.DependencyInjection/Weikio.PluginFramework.Abstractions.DependencyInjection.csproj new file mode 100644 index 0000000..cc597a4 --- /dev/null +++ b/src/Weikio.PluginFramework.Abstractions.DependencyInjection/Weikio.PluginFramework.Abstractions.DependencyInjection.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/src/Weikio.PluginFramework.AspNetCore/PluginFrameworkBuilder.cs b/src/Weikio.PluginFramework.AspNetCore/PluginFrameworkBuilder.cs new file mode 100644 index 0000000..dec62a8 --- /dev/null +++ b/src/Weikio.PluginFramework.AspNetCore/PluginFrameworkBuilder.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using Weikio.PluginFramework.Abstractions.DependencyInjection; + +namespace Weikio.PluginFramework.AspNetCore +{ + public class PluginFrameworkBuilder : IPluginFrameworkBuilder + { + public PluginFrameworkBuilder(IServiceCollection services) + { + Services = services; + } + + public IServiceCollection Services { get; } + } +} diff --git a/src/Weikio.PluginFramework.AspNetCore/PluginFrameworkBuilderExtensions.cs b/src/Weikio.PluginFramework.AspNetCore/PluginFrameworkBuilderExtensions.cs new file mode 100644 index 0000000..f1a2725 --- /dev/null +++ b/src/Weikio.PluginFramework.AspNetCore/PluginFrameworkBuilderExtensions.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Weikio.PluginFramework.Abstractions; +using Weikio.PluginFramework.Abstractions.DependencyInjection; + +namespace Weikio.PluginFramework.AspNetCore +{ + public static class PluginFrameworkBuilderExtensions + { + public static IPluginFrameworkBuilder AddPluginCatalog(this IPluginFrameworkBuilder builder, IPluginCatalog pluginCatalog) + { + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IPluginCatalog), pluginCatalog)); + + return builder; + } + + public static IPluginFrameworkBuilder AddPluginType(this IPluginFrameworkBuilder builder, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) + where T : class + { + var serviceDescriptorEnumerable = new ServiceDescriptor(typeof(IEnumerable), sp => + { + var pluginProvider = sp.GetService(); + var result = pluginProvider.GetTypes(); + + return result.AsEnumerable(); + }, serviceLifetime); + + var serviceDescriptorSingle = new ServiceDescriptor(typeof(T), sp => + { + var pluginProvider = sp.GetService(); + var result = pluginProvider.GetTypes(); + + return result.FirstOrDefault(); + }, serviceLifetime); + + builder.Services.Add(serviceDescriptorEnumerable); + builder.Services.Add(serviceDescriptorSingle); + + return builder; + } + } +} diff --git a/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs b/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs index 203ccee..bd9fe8d 100644 --- a/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs +++ b/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using Weikio.PluginFramework.Abstractions; +using Weikio.PluginFramework.Abstractions.DependencyInjection; using Weikio.PluginFramework.AspNetCore; using Weikio.PluginFramework.Catalogs; using Weikio.PluginFramework.Configuration; @@ -21,8 +22,10 @@ namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionExtensions { - public static IServiceCollection AddPluginFramework(this IServiceCollection services, Action configure = null) + public static IPluginFrameworkBuilder AddPluginFramework(this IServiceCollection services, Action configure = null) { + var frameworkBuilder = new PluginFrameworkBuilder(services); + if (configure != null) { services.Configure(configure); @@ -56,7 +59,7 @@ public static IServiceCollection AddPluginFramework(this IServiceCollection serv if (string.IsNullOrWhiteSpace(aspNetCoreControllerAssemblyLocation)) { - return services; + return frameworkBuilder; } var aspNetCoreLocation = Path.GetDirectoryName(aspNetCoreControllerAssemblyLocation); @@ -71,11 +74,13 @@ public static IServiceCollection AddPluginFramework(this IServiceCollection serv PluginLoadContextOptions.Defaults.AdditionalRuntimePaths.Add(aspNetCoreLocation); } - return services; + return frameworkBuilder; } - public static IServiceCollection AddPluginFramework(this IServiceCollection services, string dllPath = "") where TType : class + public static IPluginFrameworkBuilder AddPluginFramework(this IServiceCollection services, string dllPath = "") where TType : class { + var frameworkBuilder = new PluginFrameworkBuilder(services); + services.AddPluginFramework(); if (string.IsNullOrWhiteSpace(dllPath)) @@ -97,11 +102,11 @@ public static IServiceCollection AddPluginFramework(this IServiceCollecti .Build(); var catalog = new FolderPluginCatalog(dllPath, typeFinderCriteria); - services.AddPluginCatalog(catalog); + frameworkBuilder.AddPluginCatalog(catalog); - services.AddPluginType(); + frameworkBuilder.AddPluginType(); - return services; + return frameworkBuilder; } /// @@ -170,37 +175,5 @@ private static IServiceCollection AddConfiguration(this IServiceCollection servi return services; } - - public static IServiceCollection AddPluginCatalog(this IServiceCollection services, IPluginCatalog pluginCatalog) - { - services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IPluginCatalog), pluginCatalog)); - - return services; - } - - public static IServiceCollection AddPluginType(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) - where T : class - { - var serviceDescriptorEnumerable = new ServiceDescriptor(typeof(IEnumerable), sp => - { - var pluginProvider = sp.GetService(); - var result = pluginProvider.GetTypes(); - - return result.AsEnumerable(); - }, serviceLifetime); - - var serviceDescriptorSingle = new ServiceDescriptor(typeof(T), sp => - { - var pluginProvider = sp.GetService(); - var result = pluginProvider.GetTypes(); - - return result.FirstOrDefault(); - }, serviceLifetime); - - services.Add(serviceDescriptorEnumerable); - services.Add(serviceDescriptorSingle); - - return services; - } } } diff --git a/src/Weikio.PluginFramework.AspNetCore/Weikio.PluginFramework.AspNetCore.csproj b/src/Weikio.PluginFramework.AspNetCore/Weikio.PluginFramework.AspNetCore.csproj index b127aef..f4b01e0 100644 --- a/src/Weikio.PluginFramework.AspNetCore/Weikio.PluginFramework.AspNetCore.csproj +++ b/src/Weikio.PluginFramework.AspNetCore/Weikio.PluginFramework.AspNetCore.csproj @@ -27,6 +27,7 @@ + diff --git a/src/Weikio.PluginFramework.Catalogs.NuGet/NugetFeedCatalogConfigurationConverter.cs b/src/Weikio.PluginFramework.Catalogs.NuGet/NugetFeedCatalogConfigurationConverter.cs new file mode 100644 index 0000000..7517834 --- /dev/null +++ b/src/Weikio.PluginFramework.Catalogs.NuGet/NugetFeedCatalogConfigurationConverter.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.Configuration; +using Weikio.NugetDownloader; +using Weikio.PluginFramework.Abstractions; +using Weikio.PluginFramework.Configuration.Converters; +using Weikio.PluginFramework.TypeFinding; + +namespace Weikio.PluginFramework.Catalogs.NuGet +{ + public class NugetFeedCatalogConfigurationConverter : IConfigurationToCatalogConverter + { + public bool CanConvert(string type) + { + return string.Equals(type, "NugetFeed", StringComparison.InvariantCultureIgnoreCase); + } + + public IPluginCatalog Convert(IConfigurationSection configuration) + { + var feedName = configuration.GetValue("Name") + ?? throw new ArgumentException("Plugin Framework's NugetFeedCatalog requires a NuGet package name."); + + var feedUrl = configuration.GetValue("Feed") + ?? throw new ArgumentException("Plugin Framework's NugetFeedCatalog requires a NuGet feed url."); + + var searchTerm = configuration.GetValue("SearchTerm") + ?? throw new ArgumentException("Plugin Framework's NugetFeedCatalog requires a NuGet search term"); + + var options = new NugetFeedOptions(); + configuration.Bind("Options", options); + + return new NugetFeedPluginCatalog(new NuGetFeed(feedName, feedUrl) + { + Username = options.UserName, + Password = options.Password + }, searchTerm, options.IncludePreRelease, options.MaxPackages ?? 128); + } + } + + class NugetFeedOptions + { + public string UserName { get; set; } + + public string Password { get; set; } + + public bool IncludePreRelease { get; set; } + + public int? MaxPackages { get; set; } + } +} diff --git a/src/Weikio.PluginFramework.Catalogs.NuGet/NugetPackageCatalogConfigurationConverter.cs b/src/Weikio.PluginFramework.Catalogs.NuGet/NugetPackageCatalogConfigurationConverter.cs new file mode 100644 index 0000000..8ec0890 --- /dev/null +++ b/src/Weikio.PluginFramework.Catalogs.NuGet/NugetPackageCatalogConfigurationConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Extensions.Configuration; +using Weikio.PluginFramework.Abstractions; +using Weikio.PluginFramework.Configuration.Converters; + +namespace Weikio.PluginFramework.Catalogs.NuGet +{ + public class NugetPackageCatalogConfigurationConverter : IConfigurationToCatalogConverter + { + public bool CanConvert(string type) + { + return string.Equals(type, "NugetPackage", StringComparison.InvariantCultureIgnoreCase); + } + + public IPluginCatalog Convert(IConfigurationSection configuration) + { + var packageName = configuration.GetValue("Name") + ?? throw new ArgumentException("Plugin Framework's NugetPackageCatalog requires a NuGet package name."); + + var packageVersion = configuration.GetValue("Version") + ?? throw new ArgumentException("Plugin Framework's NugetPackageCatalog requires a NuGet package version."); + + return new NugetPackagePluginCatalog(packageName, packageVersion, true); + } + } +} diff --git a/src/Weikio.PluginFramework.Catalogs.NuGet/PluginFrameworkBuilderExtensions.cs b/src/Weikio.PluginFramework.Catalogs.NuGet/PluginFrameworkBuilderExtensions.cs new file mode 100644 index 0000000..ec68ed8 --- /dev/null +++ b/src/Weikio.PluginFramework.Catalogs.NuGet/PluginFrameworkBuilderExtensions.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using Weikio.PluginFramework.Abstractions.DependencyInjection; +using Weikio.PluginFramework.Configuration.Converters; + +namespace Weikio.PluginFramework.Catalogs.NuGet +{ + public static class PluginFrameworkBuilderExtensions + { + public static IPluginFrameworkBuilder AddNugetConfiguration(this IPluginFrameworkBuilder builder) + { + builder.Services.AddTransient(typeof(IConfigurationToCatalogConverter), typeof(NugetFeedCatalogConfigurationConverter)); + builder.Services.AddTransient(typeof(IConfigurationToCatalogConverter), typeof(NugetPackageCatalogConfigurationConverter)); + + return builder; + } + } +} diff --git a/src/Weikio.PluginFramework.Catalogs.NuGet/Weikio.PluginFramework.Catalogs.NuGet.csproj b/src/Weikio.PluginFramework.Catalogs.NuGet/Weikio.PluginFramework.Catalogs.NuGet.csproj index 22a0dbd..1c928a0 100644 --- a/src/Weikio.PluginFramework.Catalogs.NuGet/Weikio.PluginFramework.Catalogs.NuGet.csproj +++ b/src/Weikio.PluginFramework.Catalogs.NuGet/Weikio.PluginFramework.Catalogs.NuGet.csproj @@ -26,7 +26,9 @@ + +