diff --git a/samples/WebAppPluginsLibrary/CustomPlugin.cs b/samples/WebAppPluginsLibrary/CustomPlugin.cs
new file mode 100644
index 0000000..de05486
--- /dev/null
+++ b/samples/WebAppPluginsLibrary/CustomPlugin.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace WebAppPluginsLibrary
+{
+ public class CustomPlugin
+ {
+ }
+}
diff --git a/samples/WebAppPluginsLibrary/WebAppPluginsLibrary.csproj b/samples/WebAppPluginsLibrary/WebAppPluginsLibrary.csproj
new file mode 100644
index 0000000..2756020
--- /dev/null
+++ b/samples/WebAppPluginsLibrary/WebAppPluginsLibrary.csproj
@@ -0,0 +1,7 @@
+
+
+
+ netstandard2.0
+
+
+
diff --git a/samples/WebAppWithAppSettings/Controllers/CalculatorController.cs b/samples/WebAppWithAppSettings/Controllers/CalculatorController.cs
new file mode 100644
index 0000000..21d1ae0
--- /dev/null
+++ b/samples/WebAppWithAppSettings/Controllers/CalculatorController.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+using Weikio.PluginFramework.Abstractions;
+using Weikio.PluginFramework.AspNetCore;
+using Weikio.PluginFramework.Samples.Shared;
+
+namespace WebAppWithAppSettings.Controllers
+{
+ [ApiController]
+ [Route("[controller]")]
+ public class CalculatorController : ControllerBase
+ {
+ private readonly IEnumerable _plugins;
+ private readonly IServiceProvider _serviceProvider;
+ private readonly PluginProvider _pluginProvider;
+
+ public CalculatorController(IEnumerable plugins, IServiceProvider serviceProvider, PluginProvider pluginProvider)
+ {
+ _plugins = plugins;
+ _serviceProvider = serviceProvider;
+ _pluginProvider = pluginProvider;
+ }
+
+ [HttpGet]
+ public string Get()
+ {
+ var result = new StringBuilder();
+
+ result.AppendLine("All:");
+ foreach (var plugin in _plugins)
+ {
+ result.AppendLine($"{plugin.Name}: {plugin.Version}, Tags: {string.Join(", ", plugin.Tags)}");
+ }
+
+ var mathPlugins = _pluginProvider.GetByTag("MathOperator");
+ var value1 = 10;
+ var value2 = 20;
+
+ result.AppendLine($"Math operations with values {value1} and {value2}");
+
+ foreach (var mathPlugin in mathPlugins)
+ {
+ var mathPluginInstance = _serviceProvider.Create(mathPlugin);
+
+ var mathResult = mathPluginInstance.Calculate(value1, value2);
+ result.AppendLine($"{mathPlugin.Name}: {mathResult}");
+ }
+
+ return result.ToString();
+ }
+ }
+}
diff --git a/samples/WebAppWithAppSettings/Program.cs b/samples/WebAppWithAppSettings/Program.cs
new file mode 100644
index 0000000..2ee2dc8
--- /dev/null
+++ b/samples/WebAppWithAppSettings/Program.cs
@@ -0,0 +1,20 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+
+namespace WebAppWithAppSettings
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/samples/WebAppWithAppSettings/Properties/launchSettings.json b/samples/WebAppWithAppSettings/Properties/launchSettings.json
new file mode 100644
index 0000000..6b1360f
--- /dev/null
+++ b/samples/WebAppWithAppSettings/Properties/launchSettings.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "WebAppWithAppSettings": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "launchUrl": "Calculator",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:5001;http://localhost:5000"
+ }
+ }
+}
diff --git a/samples/WebAppWithAppSettings/Startup.cs b/samples/WebAppWithAppSettings/Startup.cs
new file mode 100644
index 0000000..ccaef96
--- /dev/null
+++ b/samples/WebAppWithAppSettings/Startup.cs
@@ -0,0 +1,40 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Weikio.PluginFramework.Samples.Shared;
+using Weikio.PluginFramework.TypeFinding;
+
+namespace WebAppWithAppSettings
+{
+ public class Startup
+ {
+ 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.AddControllers();
+ }
+
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseHttpsRedirection();
+
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ });
+ }
+ }
+}
diff --git a/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj b/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj
new file mode 100644
index 0000000..0462758
--- /dev/null
+++ b/samples/WebAppWithAppSettings/WebAppWithAppSettings.csproj
@@ -0,0 +1,21 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+ Never
+
+
+
+
+
diff --git a/samples/WebAppWithAppSettings/appsettings.Development.json b/samples/WebAppWithAppSettings/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/samples/WebAppWithAppSettings/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/samples/WebAppWithAppSettings/appsettings.json b/samples/WebAppWithAppSettings/appsettings.json
new file mode 100644
index 0000000..0ae908b
--- /dev/null
+++ b/samples/WebAppWithAppSettings/appsettings.json
@@ -0,0 +1,14 @@
+{
+ "PluginFramework": {
+ "Catalogs": [
+ {
+ "Type": "Folder",
+ "Path": "..\\Shared\\Weikio.PluginFramework.Samples.SharedPlugins\\bin\\debug\\netcoreapp3.1"
+ },
+ {
+ "Type": "Assembly",
+ "Path": ".\\bin\\Debug\\netcoreapp3.1\\WebAppPluginsLibrary.dll"
+ }
+ ]
+ }
+}
diff --git a/src/PluginFramework.sln b/src/PluginFramework.sln
index 5035a3f..235d067 100644
--- a/src/PluginFramework.sln
+++ b/src/PluginFramework.sln
@@ -63,6 +63,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsPluginsLibrary", ".
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "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}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAppPluginsLibrary", "..\samples\WebAppPluginsLibrary\WebAppPluginsLibrary.csproj", "{38CCE0F7-F998-4766-A14A-44C047E8D0AA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -173,6 +177,14 @@ Global
{882BB58E-D256-4BBF-8C5F-80C4FA39B775}.Debug|Any CPU.Build.0 = Debug|Any CPU
{882BB58E-D256-4BBF-8C5F-80C4FA39B775}.Release|Any CPU.ActiveCfg = Release|Any CPU
{882BB58E-D256-4BBF-8C5F-80C4FA39B775}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A5FAE1A5-74A0-4A83-9520-DCABF6610ADE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A5FAE1A5-74A0-4A83-9520-DCABF6610ADE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A5FAE1A5-74A0-4A83-9520-DCABF6610ADE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A5FAE1A5-74A0-4A83-9520-DCABF6610ADE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {38CCE0F7-F998-4766-A14A-44C047E8D0AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -200,6 +212,8 @@ Global
{A7EC9D91-CED0-43E7-BAB3-3B72230BFC0B} = {FF3A507D-D242-44F6-8940-49E0B51B6F02}
{6D392453-FC9E-45AD-A9A7-7596A93B3E6C} = {FF3A507D-D242-44F6-8940-49E0B51B6F02}
{E92B0C5D-FFAC-4AB9-B069-869AEED565B0} = {FF3A507D-D242-44F6-8940-49E0B51B6F02}
+ {A5FAE1A5-74A0-4A83-9520-DCABF6610ADE} = {FF3A507D-D242-44F6-8940-49E0B51B6F02}
+ {38CCE0F7-F998-4766-A14A-44C047E8D0AA} = {FF3A507D-D242-44F6-8940-49E0B51B6F02}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AAEBC2B4-FB52-4272-8C25-571FB3CA01E5}
diff --git a/src/Weikio.PluginFramework.Abstractions/PluginFrameworkOptions.cs b/src/Weikio.PluginFramework.Abstractions/PluginFrameworkOptions.cs
new file mode 100644
index 0000000..d8fe9ab
--- /dev/null
+++ b/src/Weikio.PluginFramework.Abstractions/PluginFrameworkOptions.cs
@@ -0,0 +1,11 @@
+namespace Weikio.PluginFramework.Abstractions
+{
+ ///
+ /// Configures the options for Plugin Framework.
+ ///
+ public class PluginFrameworkOptions
+ {
+ public bool UseConfiguration { get; set; } = true;
+ public string ConfigurationSection { get; set; } = "PluginFramework";
+ }
+}
diff --git a/src/Weikio.PluginFramework.AspNetCore/PluginProvider.cs b/src/Weikio.PluginFramework.AspNetCore/PluginProvider.cs
new file mode 100644
index 0000000..901912a
--- /dev/null
+++ b/src/Weikio.PluginFramework.AspNetCore/PluginProvider.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.DependencyInjection;
+using Weikio.PluginFramework.Abstractions;
+
+namespace Weikio.PluginFramework.AspNetCore
+{
+ public class PluginProvider
+ {
+ private readonly IEnumerable _catalogs;
+ private readonly IServiceProvider _serviceProvider;
+
+ public PluginProvider(IEnumerable catalogs, IServiceProvider serviceProvider)
+ {
+ _catalogs = catalogs;
+ _serviceProvider = serviceProvider;
+ }
+
+ public List GetByTag(string tag)
+ {
+ var result = new List();
+
+ foreach (var pluginCatalog in _catalogs)
+ {
+ var pluginsByTag = pluginCatalog.GetByTag(tag);
+ result.AddRange(pluginsByTag);
+ }
+
+ return result;
+ }
+
+ public List GetPlugins()
+ {
+ var result = new List();
+ foreach (var pluginCatalog in _catalogs)
+ {
+ result.AddRange(pluginCatalog.GetPlugins());
+ }
+
+ return result;
+ }
+
+ public Plugin Get(string name, Version version)
+ {
+ foreach (var pluginCatalog in _catalogs)
+ {
+ var result = pluginCatalog.Get(name, version);
+
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ public List GetTypes() where T : class
+ {
+ var result = new List();
+ var catalogs = _serviceProvider.GetServices();
+
+ foreach (var catalog in catalogs)
+ {
+ var plugins = catalog.GetPlugins();
+
+ foreach (var plugin in plugins.Where(x => typeof(T).IsAssignableFrom(x)))
+ {
+ var op = plugin.Create(_serviceProvider);
+
+ result.Add(op);
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs b/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs
index 2637dac..203ccee 100644
--- a/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs
+++ b/src/Weikio.PluginFramework.AspNetCore/ServiceCollectionExtensions.cs
@@ -6,6 +6,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Options;
using Weikio.PluginFramework.Abstractions;
using Weikio.PluginFramework.AspNetCore;
using Weikio.PluginFramework.Catalogs;
@@ -20,9 +21,21 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
- public static IServiceCollection AddPluginFramework(this IServiceCollection services)
+ public static IServiceCollection AddPluginFramework(this IServiceCollection services, Action configure = null)
{
+ if (configure != null)
+ {
+ services.Configure(configure);
+ }
+
services.AddHostedService();
+ services.AddTransient();
+
+ services.TryAddTransient(typeof(IPluginCatalogConfigurationLoader), typeof(PluginCatalogConfigurationLoader));
+ services.AddTransient(typeof(IConfigurationToCatalogConverter), typeof(FolderCatalogConfigurationConverter));
+ services.AddTransient(typeof(IConfigurationToCatalogConverter), typeof(AssemblyCatalogConfigurationCoverter));
+
+ services.AddConfiguration();
services.AddSingleton(sp =>
{
@@ -47,7 +60,7 @@ public static IServiceCollection AddPluginFramework(this IServiceCollection serv
}
var aspNetCoreLocation = Path.GetDirectoryName(aspNetCoreControllerAssemblyLocation);
-
+
if (PluginLoadContextOptions.Defaults.AdditionalRuntimePaths == null)
{
PluginLoadContextOptions.Defaults.AdditionalRuntimePaths = new List();
@@ -60,7 +73,7 @@ public static IServiceCollection AddPluginFramework(this IServiceCollection serv
return services;
}
-
+
public static IServiceCollection AddPluginFramework(this IServiceCollection services, string dllPath = "") where TType : class
{
services.AddPluginFramework();
@@ -87,81 +100,74 @@ public static IServiceCollection AddPluginFramework(this IServiceCollecti
services.AddPluginCatalog(catalog);
services.AddPluginType();
-
+
return services;
}
///
- /// Add plugins from the provided object.
+ /// Add plugins from the IConfiguration.
///
/// The on which the plugins will be added.
- /// The object that contains the plugin configurations.
/// This .
- public static IServiceCollection AddPluginFramework(
- this IServiceCollection services,
- IConfiguration configuration)
+ private static IServiceCollection AddConfiguration(this IServiceCollection services)
{
- // Register the default implementation of IPluginCatalogConfigurationLoader with the provided configuration.
- services.AddTransient(serviceProvider =>
- new PluginCatalogConfigurationLoader(configuration));
-
- services.TryAddSingleton((Func)(serviceProvider =>
+ services.TryAddSingleton(serviceProvider =>
{
- // Grab all the IPluginCatalogConfigurationLoader implementations to laod catalog configurations.
+ var options = serviceProvider.GetService>().Value;
+
+ if (options.UseConfiguration == false)
+ {
+ return new EmptyPluginCatalog();
+ }
+
+ // Grab all the IPluginCatalogConfigurationLoader implementations to load catalog configurations.
var loaders = serviceProvider
.GetServices()
.ToList();
- var converters = serviceProvider.GetServices();
+ var configuration = serviceProvider.GetService();
+
+ var converters = serviceProvider.GetServices().ToList();
var catalogs = new List();
foreach (var loader in loaders)
{
// Load the catalog configurations.
- var catalogConfigs = loader.GetCatalogConfigurations();
+ var catalogConfigs = loader.GetCatalogConfigurations(configuration);
- if (catalogConfigs == null || catalogConfigs.Count == 0)
+ if (catalogConfigs?.Any() != true)
{
- // if no configurations were provided continue.
continue;
}
for (var i = 0; i < catalogConfigs.Count; i++)
{
var item = catalogConfigs[i];
- var key = $"{loader.SectionKey}:{loader.CatalogsKey}:{i}";
+ var key = $"{options.ConfigurationSection}:{loader.CatalogsKey}:{i}";
// Check if a type is provided.
- var type = string.IsNullOrWhiteSpace(item.Type)
- ? throw new ArgumentException($"A type must be provided for catalog at position {i + 1}")
- : item.Type;
+ if (string.IsNullOrWhiteSpace(item.Type))
+ {
+ throw new ArgumentException($"A type must be provided for catalog at position {i + 1}");
+ }
// Try to find any registered converter that can convert the specified type.
- var foundConverter = converters.FirstOrDefault(converter => converter.CanConvert(type));
-
- // Add a catalog to the list of catalogs.
- catalogs.Add(foundConverter != null
- // If a converter was found we call it's convert method.
- ? foundConverter.Convert(loader.Configuration.GetSection(key))
- // If no converter was found (it's null) we proceed with the built-in type converters.
- : type switch
- {
- // Assembly type.
- CatalogTypes.Assembly => new AssemblyCatalogConfigurationCoverter().Convert(configuration.GetSection(key)),
-
- // Folder type.
- CatalogTypes.Folder => new FolderCatalogConfigurationConverter().Convert(configuration.GetSection(key)),
-
- // Unkown type.
- _ => throw new ArgumentException($"The type provided for catalog at position {i + 1} is unknown.")
- });
+ var foundConverter = converters.FirstOrDefault(converter => converter.CanConvert(item.Type));
+
+ if (foundConverter == null)
+ {
+ throw new ArgumentException($"The type provided for Plugin catalog at position {i + 1} is unknown.");
+ }
+
+ var catalog = foundConverter.Convert(configuration.GetSection(key));
+
+ catalogs.Add(catalog);
}
}
return new CompositePluginCatalog(catalogs.ToArray());
- }));
+ });
- services.AddPluginFramework();
return services;
}
@@ -172,22 +178,23 @@ public static IServiceCollection AddPluginCatalog(this IServiceCollection servic
return services;
}
- public static IServiceCollection AddPluginType(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) where T : class
+ public static IServiceCollection AddPluginType(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
+ where T : class
{
var serviceDescriptorEnumerable = new ServiceDescriptor(typeof(IEnumerable), sp =>
{
- var result = GetTypes(sp);
+ var pluginProvider = sp.GetService();
+ var result = pluginProvider.GetTypes();
return result.AsEnumerable();
-
}, serviceLifetime);
-
+
var serviceDescriptorSingle = new ServiceDescriptor(typeof(T), sp =>
{
- var result = GetTypes(sp);
+ var pluginProvider = sp.GetService();
+ var result = pluginProvider.GetTypes();
return result.FirstOrDefault();
-
}, serviceLifetime);
services.Add(serviceDescriptorEnumerable);
@@ -195,25 +202,5 @@ public static IServiceCollection AddPluginType(this IServiceCollection servic
return services;
}
-
- private static List GetTypes(IServiceProvider sp) where T : class
- {
- var result = new List();
- var catalogs = sp.GetServices();
-
- foreach (var catalog in catalogs)
- {
- var plugins = catalog.GetPlugins();
-
- foreach (var plugin in plugins.Where(x => typeof(T).IsAssignableFrom(x)))
- {
- var op = plugin.Create(sp);
-
- result.Add(op);
- }
- }
-
- return result;
- }
}
}
diff --git a/src/Weikio.PluginFramework.AspNetCore/ServiceProviderExtensions.cs b/src/Weikio.PluginFramework.AspNetCore/ServiceProviderExtensions.cs
index 4b98d68..447ed92 100644
--- a/src/Weikio.PluginFramework.AspNetCore/ServiceProviderExtensions.cs
+++ b/src/Weikio.PluginFramework.AspNetCore/ServiceProviderExtensions.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using Weikio.PluginFramework.Abstractions;
// ReSharper disable once CheckNamespace
diff --git a/src/Weikio.PluginFramework.Configuration/CatalogTypes.cs b/src/Weikio.PluginFramework.Configuration/CatalogTypes.cs
deleted file mode 100644
index 16e58ff..0000000
--- a/src/Weikio.PluginFramework.Configuration/CatalogTypes.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Weikio.PluginFramework.Configuration
-{
- ///
- /// Static class tha contains the Types and their keys
- /// that can be configured from a configuration.
- ///
- public static class CatalogTypes
- {
- public const string Assembly = "Assembly";
- public const string Folder = "Folder";
- }
-}
diff --git a/src/Weikio.PluginFramework.Configuration/Converters/AssemblyCatalogConfigurationCoverter.cs b/src/Weikio.PluginFramework.Configuration/Converters/AssemblyCatalogConfigurationCoverter.cs
index 0a29d1f..d1f0ef9 100644
--- a/src/Weikio.PluginFramework.Configuration/Converters/AssemblyCatalogConfigurationCoverter.cs
+++ b/src/Weikio.PluginFramework.Configuration/Converters/AssemblyCatalogConfigurationCoverter.cs
@@ -1,3 +1,4 @@
+using System;
using Microsoft.Extensions.Configuration;
using Weikio.PluginFramework.Abstractions;
using Weikio.PluginFramework.Catalogs;
@@ -12,7 +13,7 @@ public class AssemblyCatalogConfigurationCoverter : IConfigurationToCatalogConve
///
public bool CanConvert(string type)
{
- return type == CatalogTypes.Assembly;
+ return string.Equals(type, "Assembly", StringComparison.InvariantCultureIgnoreCase);
}
///
diff --git a/src/Weikio.PluginFramework.Configuration/Converters/FolderCatalogConfigurationConverter.cs b/src/Weikio.PluginFramework.Configuration/Converters/FolderCatalogConfigurationConverter.cs
index 131a467..ecf92db 100644
--- a/src/Weikio.PluginFramework.Configuration/Converters/FolderCatalogConfigurationConverter.cs
+++ b/src/Weikio.PluginFramework.Configuration/Converters/FolderCatalogConfigurationConverter.cs
@@ -14,14 +14,14 @@ public class FolderCatalogConfigurationConverter : IConfigurationToCatalogConver
///
public bool CanConvert(string type)
{
- return type == CatalogTypes.Folder;
+ return string.Equals(type, "Folder", StringComparison.InvariantCultureIgnoreCase);
}
///
public IPluginCatalog Convert(IConfigurationSection configuration)
{
var path = configuration.GetValue("Path")
- ?? throw new ArgumentException("PuglinFramework FolderCatalog requires a Path.");
+ ?? throw new ArgumentException("Plugin Framework's FolderCatalog requires a Path.");
var options = new CatalogFolderOptions();
configuration.Bind($"Options", options);
diff --git a/src/Weikio.PluginFramework.Configuration/Providers/IPluginCatalogConfigurationLoader.cs b/src/Weikio.PluginFramework.Configuration/Providers/IPluginCatalogConfigurationLoader.cs
index ab2206f..b3bb115 100644
--- a/src/Weikio.PluginFramework.Configuration/Providers/IPluginCatalogConfigurationLoader.cs
+++ b/src/Weikio.PluginFramework.Configuration/Providers/IPluginCatalogConfigurationLoader.cs
@@ -8,26 +8,16 @@ namespace Weikio.PluginFramework.Configuration.Providers
///
public interface IPluginCatalogConfigurationLoader
{
- ///
- /// The key of the section inside the configuration.
- ///
- string SectionKey { get; }
-
///
/// The key of the catalogs section inside the parent configuration section ().
///
string CatalogsKey { get; }
- ///
- /// The configuration that contains the options to load.
- ///
- IConfiguration Configuration { get; }
-
///
/// Returns a list that contains catalog configurations.
///
/// The configuration to use.
/// A list that contains catalog configurations.
- List GetCatalogConfigurations();
+ List GetCatalogConfigurations(IConfiguration configuration);
}
}
diff --git a/src/Weikio.PluginFramework.Configuration/Providers/PluginCatalogConfigurationLoader.cs b/src/Weikio.PluginFramework.Configuration/Providers/PluginCatalogConfigurationLoader.cs
index 4bf63eb..68862bd 100644
--- a/src/Weikio.PluginFramework.Configuration/Providers/PluginCatalogConfigurationLoader.cs
+++ b/src/Weikio.PluginFramework.Configuration/Providers/PluginCatalogConfigurationLoader.cs
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using Weikio.PluginFramework.Abstractions;
namespace Weikio.PluginFramework.Configuration.Providers
{
@@ -9,26 +11,22 @@ namespace Weikio.PluginFramework.Configuration.Providers
///
public class PluginCatalogConfigurationLoader : IPluginCatalogConfigurationLoader
{
- ///
- public virtual string SectionKey => "PluginFramework";
+ private PluginFrameworkOptions _options;
///
public virtual string CatalogsKey => "Catalogs";
- ///
- public IConfiguration Configuration { get; private set; }
-
- public PluginCatalogConfigurationLoader(IConfiguration configuration)
+ public PluginCatalogConfigurationLoader(IOptions options)
{
- Configuration = configuration;
+ _options = options.Value;
}
///
- public List GetCatalogConfigurations()
+ public List GetCatalogConfigurations(IConfiguration configuration)
{
var catalogs = new List();
- Configuration.Bind($"{SectionKey}:{CatalogsKey}", catalogs);
+ configuration.Bind($"{_options.ConfigurationSection}:{CatalogsKey}", catalogs);
return catalogs;
}
diff --git a/src/Weikio.PluginFramework.Configuration/Weikio.PluginFramework.Configuration.csproj b/src/Weikio.PluginFramework.Configuration/Weikio.PluginFramework.Configuration.csproj
index a1db89b..2247c2f 100644
--- a/src/Weikio.PluginFramework.Configuration/Weikio.PluginFramework.Configuration.csproj
+++ b/src/Weikio.PluginFramework.Configuration/Weikio.PluginFramework.Configuration.csproj
@@ -3,10 +3,24 @@
netcoreapp3.1
enable
+ true
+ true
+ IConfiguration support for Plugin Framework.
+ IConfiguration support for Plugin Framework.
+ Weikio.PluginFramework.Configuration
+ Weikio.PluginFramework.Configuration
+ Weikio.PluginFramework.Configuration
+ plugins;addons;aspnetextensions;plugin framework;configuration
+ logo_transparent_color_256.png
+ IConfiguration support for Plugin Framework
-
+
+
+
+
+
diff --git a/src/Weikio.PluginFramework/Catalogs/AssemblyPluginCatalog.cs b/src/Weikio.PluginFramework/Catalogs/AssemblyPluginCatalog.cs
index fa9d109..7eebebc 100644
--- a/src/Weikio.PluginFramework/Catalogs/AssemblyPluginCatalog.cs
+++ b/src/Weikio.PluginFramework/Catalogs/AssemblyPluginCatalog.cs
@@ -185,12 +185,20 @@ public async Task Initialize()
var finder = new TypeFinder();
+ var handledPluginTypes = new List();
foreach (var typeFinderCriteria in _options.TypeFinderOptions.TypeFinderCriterias)
{
var pluginTypes = finder.Find(typeFinderCriteria, _assembly, _pluginAssemblyLoadContext);
foreach (var type in pluginTypes)
{
+ if (handledPluginTypes.Contains(type))
+ {
+ // Make sure to create only a single type plugin catalog for each plugin type.
+ // The type catalog will add all the matching tags
+ continue;
+ }
+
var typePluginCatalog = new TypePluginCatalog(type,
new TypePluginCatalogOptions()
{
@@ -202,6 +210,8 @@ public async Task Initialize()
await typePluginCatalog.Initialize();
_plugins.Add(typePluginCatalog);
+
+ handledPluginTypes.Add(type);
}
}
diff --git a/tests/unit/Weikio.PluginFramework.Tests/TagTests.cs b/tests/unit/Weikio.PluginFramework.Tests/TagTests.cs
index 50428be..a9dd454 100644
--- a/tests/unit/Weikio.PluginFramework.Tests/TagTests.cs
+++ b/tests/unit/Weikio.PluginFramework.Tests/TagTests.cs
@@ -137,6 +137,7 @@ public DefaultOptions()
{
TypeFinderOptions.Defaults.TypeFinderCriterias.Add(TypeFinderCriteriaBuilder.Create().Tag("CustomTag"));
TypeFinderOptions.Defaults.TypeFinderCriterias.Add(TypeFinderCriteriaBuilder.Create().HasName(nameof(TypePlugin)).Tag("MyTag_1"));
+ TypeFinderOptions.Defaults.TypeFinderCriterias.Add(TypeFinderCriteriaBuilder.Create().HasName("*Json*").Tag("MyTag_1"));
}
[Fact]
@@ -158,6 +159,32 @@ public async Task CanTagUsingDefaultOptions()
TypeFinderOptions.Defaults.TypeFinderCriterias.Clear();
}
+ [Fact]
+ public async Task DefaultTagsWithFolderCatalogTypeShouldNotDuplicatePlugins()
+ {
+ var catalog = new FolderPluginCatalog(@"..\..\..\..\..\Assemblies\bin\JsonNew\netstandard2.0");
+ await catalog.Initialize();
+
+ Assert.Single(catalog.GetPlugins());
+ var plugin = catalog.Get();
+
+ Assert.Equal(2, plugin.Tags.Count);
+ TypeFinderOptions.Defaults.TypeFinderCriterias.Clear();
+ }
+
+ [Fact]
+ public async Task DefaultTagsWithAssemblyCatalogTypeShouldNotDuplicatePlugins()
+ {
+ var catalog = new AssemblyPluginCatalog(@"..\..\..\..\..\Assemblies\bin\JsonNew\netstandard2.0\JsonNetNew.dll");
+ await catalog.Initialize();
+
+ Assert.Single(catalog.GetPlugins());
+ var plugin = catalog.Get();
+
+ Assert.Equal(2, plugin.Tags.Count);
+ TypeFinderOptions.Defaults.TypeFinderCriterias.Clear();
+ }
+
public void Dispose()
{
TypeFinderOptions.Defaults.TypeFinderCriterias.Clear();