diff --git a/backend/src/Squidex.Infrastructure/Plugins/IWebPlugin.cs b/backend/extensions/Squidex.SamplePlugin/SamplePlugin.cs
similarity index 50%
rename from backend/src/Squidex.Infrastructure/Plugins/IWebPlugin.cs
rename to backend/extensions/Squidex.SamplePlugin/SamplePlugin.cs
index 0fb417b3a..c12b5ce22 100644
--- a/backend/src/Squidex.Infrastructure/Plugins/IWebPlugin.cs
+++ b/backend/extensions/Squidex.SamplePlugin/SamplePlugin.cs
@@ -5,14 +5,18 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
-using Microsoft.AspNetCore.Builder;
+using System;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Squidex.Infrastructure.Plugins;
-namespace Squidex.Infrastructure.Plugins
+namespace Squidex.SamplePlugin
{
- public interface IWebPlugin : IPlugin
+ public sealed class SamplePlugin : IPlugin
{
- void ConfigureBefore(IApplicationBuilder app);
-
- void ConfigureAfter(IApplicationBuilder app);
+ public void ConfigureServices(IServiceCollection services, IConfiguration config)
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/backend/extensions/Squidex.SamplePlugin/Squidex.SamplePlugin.csproj b/backend/extensions/Squidex.SamplePlugin/Squidex.SamplePlugin.csproj
new file mode 100644
index 000000000..fd84a73aa
--- /dev/null
+++ b/backend/extensions/Squidex.SamplePlugin/Squidex.SamplePlugin.csproj
@@ -0,0 +1,20 @@
+
+
+ netcoreapp3.0
+ 8.0
+
+
+
+
+
+
+
+
+
+
+ ..\..\Squidex.ruleset
+
+
+
+
+
diff --git a/backend/src/Squidex/Pipeline/Plugins/PluginLoaders.cs b/backend/src/Squidex.Infrastructure/Plugins/PluginLoaders.cs
similarity index 74%
rename from backend/src/Squidex/Pipeline/Plugins/PluginLoaders.cs
rename to backend/src/Squidex.Infrastructure/Plugins/PluginLoaders.cs
index d2471144f..d988b42e0 100644
--- a/backend/src/Squidex/Pipeline/Plugins/PluginLoaders.cs
+++ b/backend/src/Squidex.Infrastructure/Plugins/PluginLoaders.cs
@@ -8,32 +8,14 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Reflection;
using McMaster.NETCore.Plugins;
-using Squidex.Domain.Apps.Core;
-using Squidex.Domain.Apps.Entities;
-using Squidex.Domain.Apps.Events;
-using Squidex.Infrastructure;
-using Squidex.Infrastructure.Plugins;
-using Squidex.Web;
-namespace Squidex.Pipeline.Plugins
+namespace Squidex.Infrastructure.Plugins
{
public static class PluginLoaders
{
- private static readonly Type[] SharedTypes =
- {
- typeof(IPlugin),
- typeof(SquidexCoreModel),
- typeof(SquidexCoreOperations),
- typeof(SquidexEntities),
- typeof(SquidexEvents),
- typeof(SquidexInfrastructure),
- typeof(SquidexWeb)
- };
-
- public static PluginLoader? LoadPlugin(string pluginPath)
+ public static PluginLoader? LoadPlugin(string pluginPath, AssemblyName[] sharedAssemblies)
{
foreach (var candidate in GetPaths(pluginPath))
{
@@ -43,7 +25,7 @@ namespace Squidex.Pipeline.Plugins
{
config.PreferSharedTypes = true;
- config.SharedAssemblies.AddRange(SharedTypes.Select(x => x.Assembly.GetName()));
+ config.SharedAssemblies.AddRange(sharedAssemblies);
});
}
}
diff --git a/backend/src/Squidex.Infrastructure/Plugins/PluginManager.cs b/backend/src/Squidex.Infrastructure/Plugins/PluginManager.cs
index dd14f3ca3..5d1132e37 100644
--- a/backend/src/Squidex.Infrastructure/Plugins/PluginManager.cs
+++ b/backend/src/Squidex.Infrastructure/Plugins/PluginManager.cs
@@ -7,29 +7,69 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Reflection;
-using Microsoft.AspNetCore.Builder;
+using McMaster.NETCore.Plugins;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Squidex.Infrastructure.Log;
namespace Squidex.Infrastructure.Plugins
{
- public sealed class PluginManager
+ public sealed class PluginManager : DisposableObjectBase
{
+ private readonly HashSet pluginLoaders = new HashSet();
private readonly HashSet loadedPlugins = new HashSet();
private readonly List<(string Plugin, string Action, Exception Exception)> exceptions = new List<(string, string, Exception)>();
- public IReadOnlyCollection Plugins
+ protected override void DisposeObject(bool disposing)
{
- get { return loadedPlugins; }
+ if (disposing)
+ {
+ foreach (var loader in pluginLoaders)
+ {
+ loader.Dispose();
+ }
+ }
}
- public void Add(string name, Assembly assembly)
+ public Assembly? Load(string path, AssemblyName[] sharedAssemblies)
{
- Guard.NotNull(assembly);
+ Guard.NotNullOrEmpty(path);
+ Guard.NotNull(sharedAssemblies);
+
+ Assembly? assembly = null;
+
+ var loader = PluginLoaders.LoadPlugin(path, sharedAssemblies);
+
+ if (loader != null)
+ {
+ try
+ {
+ assembly = loader.LoadDefaultAssembly();
+
+ Add(path, assembly);
+
+ pluginLoaders.Add(loader);
+ }
+ catch (Exception ex)
+ {
+ LogException(path, "LoadingAssembly", ex);
+
+ loader.Dispose();
+ }
+ }
+ else
+ {
+ LogException(path, "LoadingPlugin", new FileNotFoundException($"Cannot find plugin at {path}"));
+ }
+ return assembly;
+ }
+
+ private void Add(string name, Assembly assembly)
+ {
var pluginTypes =
assembly.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t))
@@ -50,12 +90,8 @@ namespace Squidex.Infrastructure.Plugins
}
}
- public void LogException(string plugin, string action, Exception exception)
+ private void LogException(string plugin, string action, Exception exception)
{
- Guard.NotNull(plugin);
- Guard.NotNull(action);
- Guard.NotNull(exception);
-
exceptions.Add((plugin, action, exception));
}
@@ -70,26 +106,6 @@ namespace Squidex.Infrastructure.Plugins
}
}
- public void ConfigureBefore(IApplicationBuilder app)
- {
- Guard.NotNull(app);
-
- foreach (var plugin in loadedPlugins.OfType())
- {
- plugin.ConfigureBefore(app);
- }
- }
-
- public void ConfigureAfter(IApplicationBuilder app)
- {
- Guard.NotNull(app);
-
- foreach (var plugin in loadedPlugins.OfType())
- {
- plugin.ConfigureAfter(app);
- }
- }
-
public void Log(ISemanticLog log)
{
Guard.NotNull(log);
diff --git a/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj b/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
index ea46d3593..259d1ff70 100644
--- a/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
+++ b/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
@@ -8,11 +8,9 @@
full
True
-
-
-
+
diff --git a/backend/src/Squidex/Pipeline/Plugins/PluginExtensions.cs b/backend/src/Squidex/Pipeline/Plugins/PluginExtensions.cs
index cab52c7fa..cebb20c00 100644
--- a/backend/src/Squidex/Pipeline/Plugins/PluginExtensions.cs
+++ b/backend/src/Squidex/Pipeline/Plugins/PluginExtensions.cs
@@ -6,7 +6,8 @@
// ==========================================================================
using System;
-using System.IO;
+using System.Linq;
+using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -17,6 +18,12 @@ namespace Squidex.Pipeline.Plugins
{
public static class PluginExtensions
{
+ private static readonly AssemblyName[] SharedAssemblies =
+ Assembly.GetEntryAssembly()!
+ .GetReferencedAssemblies()
+ .Where(x => x.Name?.StartsWith("Squidex.", StringComparison.OrdinalIgnoreCase) == true)
+ .ToArray();
+
public static IMvcBuilder AddSquidexPlugins(this IMvcBuilder mvcBuilder, IConfiguration config)
{
var pluginManager = new PluginManager();
@@ -27,25 +34,11 @@ namespace Squidex.Pipeline.Plugins
{
foreach (var path in options.Plugins)
{
- var plugin = PluginLoaders.LoadPlugin(path);
-
- if (plugin != null)
- {
- try
- {
- var pluginAssembly = plugin.LoadDefaultAssembly();
+ var pluginAssembly = pluginManager.Load(path, SharedAssemblies);
- pluginAssembly.AddParts(mvcBuilder);
- pluginManager.Add(path, pluginAssembly);
- }
- catch (Exception ex)
- {
- pluginManager.LogException(path, "LoadingAssembly", ex);
- }
- }
- else
+ if (pluginAssembly != null)
{
- pluginManager.LogException(path, "LoadingPlugin", new FileNotFoundException($"Cannot find plugin at {path}"));
+ pluginAssembly.AddParts(mvcBuilder);
}
}
}
@@ -57,20 +50,6 @@ namespace Squidex.Pipeline.Plugins
return mvcBuilder;
}
- public static void UsePluginsBefore(this IApplicationBuilder app)
- {
- var pluginManager = app.ApplicationServices.GetRequiredService();
-
- pluginManager.ConfigureBefore(app);
- }
-
- public static void UsePluginsAfter(this IApplicationBuilder app)
- {
- var pluginManager = app.ApplicationServices.GetRequiredService();
-
- pluginManager.ConfigureAfter(app);
- }
-
public static void UsePlugins(this IApplicationBuilder app)
{
var pluginManager = app.ApplicationServices.GetRequiredService();
diff --git a/backend/src/Squidex/Squidex.csproj b/backend/src/Squidex/Squidex.csproj
index 2a7c868f4..d6b3a5bef 100644
--- a/backend/src/Squidex/Squidex.csproj
+++ b/backend/src/Squidex/Squidex.csproj
@@ -38,7 +38,6 @@
-
diff --git a/backend/src/Squidex/Startup.cs b/backend/src/Squidex/Startup.cs
index 1e9cb14d7..c15572b4c 100644
--- a/backend/src/Squidex/Startup.cs
+++ b/backend/src/Squidex/Startup.cs
@@ -71,8 +71,6 @@ namespace Squidex
public void Configure(IApplicationBuilder app)
{
- app.UsePluginsBefore();
-
app.UseSquidexHealthCheck();
app.UseSquidexRobotsTxt();
app.UseSquidexTracking();
@@ -86,7 +84,6 @@ namespace Squidex
app.ConfigureIdentityServer();
app.ConfigureFrontend();
- app.UsePluginsAfter();
app.UsePlugins();
}
}