Bläddra i källkod

Merge pull request #4253 from BaronGreenback/fordiscussion

DI in plugins
Bond-009 4 år sedan
förälder
incheckning
331c7f8481

+ 27 - 0
Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs

@@ -133,6 +133,33 @@ namespace Emby.Server.Implementations.AppBase
             }
         }
 
+        /// <summary>
+        /// Manually pre-loads a factory so that it is available pre system initialisation.
+        /// </summary>
+        /// <typeparam name="T">Class to register.</typeparam>
+        public virtual void RegisterConfiguration<T>()
+            where T : IConfigurationFactory
+        {
+            IConfigurationFactory factory = Activator.CreateInstance<T>();
+
+            if (_configurationFactories == null)
+            {
+                _configurationFactories = new[] { factory };
+            }
+            else
+            {
+                var oldLen = _configurationFactories.Length;
+                var arr = new IConfigurationFactory[oldLen + 1];
+                _configurationFactories.CopyTo(arr, 0);
+                arr[oldLen] = factory;
+                _configurationFactories = arr;
+            }
+
+            _configurationStores = _configurationFactories
+                .SelectMany(i => i.GetConfigurations())
+                .ToArray();
+        }
+
         /// <summary>
         /// Adds parts.
         /// </summary>

+ 33 - 32
Emby.Server.Implementations/ApplicationHost.cs

@@ -126,7 +126,6 @@ namespace Emby.Server.Implementations
         private IMediaEncoder _mediaEncoder;
         private ISessionManager _sessionManager;
         private IHttpClientFactory _httpClientFactory;
-
         private string[] _urlPrefixes;
 
         /// <summary>
@@ -497,24 +496,11 @@ namespace Emby.Server.Implementations
                 HttpsPort = ServerConfiguration.DefaultHttpsPort;
             }
 
-            if (Plugins != null)
-            {
-                var pluginBuilder = new StringBuilder();
-
-                foreach (var plugin in Plugins)
-                {
-                    pluginBuilder.Append(plugin.Name)
-                        .Append(' ')
-                        .Append(plugin.Version)
-                        .AppendLine();
-                }
-
-                Logger.LogInformation("Plugins: {Plugins}", pluginBuilder.ToString());
-            }
-
             DiscoverTypes();
 
             RegisterServices();
+
+            RegisterPluginServices();
         }
 
         /// <summary>
@@ -779,10 +765,24 @@ namespace Emby.Server.Implementations
 
             ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
             _plugins = GetExports<IPlugin>()
-                        .Select(LoadPlugin)
                         .Where(i => i != null)
                         .ToArray();
 
+            if (Plugins != null)
+            {
+                var pluginBuilder = new StringBuilder();
+
+                foreach (var plugin in Plugins)
+                {
+                    pluginBuilder.Append(plugin.Name)
+                        .Append(' ')
+                        .Append(plugin.Version)
+                        .AppendLine();
+                }
+
+                Logger.LogInformation("Plugins: {Plugins}", pluginBuilder.ToString());
+            }
+
             _urlPrefixes = GetUrlPrefixes().ToArray();
 
             Resolve<ILibraryManager>().AddParts(
@@ -812,21 +812,6 @@ namespace Emby.Server.Implementations
             Resolve<IIsoManager>().AddParts(GetExports<IIsoMounter>());
         }
 
-        private IPlugin LoadPlugin(IPlugin plugin)
-        {
-            try
-            {
-                plugin.RegisterServices(ServiceCollection);
-            }
-            catch (Exception ex)
-            {
-                Logger.LogError(ex, "Error loading plugin {PluginName}", plugin.GetType().FullName);
-                return null;
-            }
-
-            return plugin;
-        }
-
         /// <summary>
         /// Discovers the types.
         /// </summary>
@@ -837,6 +822,22 @@ namespace Emby.Server.Implementations
             _allConcreteTypes = GetTypes(GetComposablePartAssemblies()).ToArray();
         }
 
+        private void RegisterPluginServices()
+        {
+            foreach (var pluginServiceRegistrator in GetExportTypes<IPluginServiceRegistrator>())
+            {
+                try
+                {
+                    var instance = (IPluginServiceRegistrator)Activator.CreateInstance(pluginServiceRegistrator);
+                    instance.RegisterServices(ServiceCollection);
+                }
+                catch (Exception ex)
+                {
+                    Logger.LogError(ex, "Error registering plugin services from {Assembly}.", pluginServiceRegistrator.Assembly);
+                }
+            }
+        }
+
         private IEnumerable<Type> GetTypes(IEnumerable<Assembly> assemblies)
         {
             foreach (var ass in assemblies)

+ 7 - 0
MediaBrowser.Common/Configuration/IConfigurationManager.cs

@@ -46,6 +46,13 @@ namespace MediaBrowser.Common.Configuration
         /// <param name="newConfiguration">The new configuration.</param>
         void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration);
 
+        /// <summary>
+        /// Manually pre-loads a factory so that it is available pre system initialisation.
+        /// </summary>
+        /// <typeparam name="T">Class to register.</typeparam>
+        void RegisterConfiguration<T>()
+            where T : IConfigurationFactory;
+
         /// <summary>
         /// Gets the configuration.
         /// </summary>

+ 7 - 10
MediaBrowser.Common/Plugins/BasePlugin.cs

@@ -83,16 +83,6 @@ namespace MediaBrowser.Common.Plugins
         {
         }
 
-        /// <inheritdoc />
-        public virtual void RegisterServices(IServiceCollection serviceCollection)
-        {
-        }
-
-        /// <inheritdoc />
-        public virtual void UnregisterServices(IServiceCollection serviceCollection)
-        {
-        }
-
         /// <inheritdoc />
         public void SetAttributes(string assemblyFilePath, string dataFolderPath, Version assemblyVersion)
         {
@@ -185,6 +175,11 @@ namespace MediaBrowser.Common.Plugins
         /// <value>The type of the configuration.</value>
         public Type ConfigurationType => typeof(TConfigurationType);
 
+        /// <summary>
+        /// Gets or sets the event handler that is triggered when this configuration changes.
+        /// </summary>
+        public EventHandler<BasePluginConfiguration> ConfigurationChanged { get; set; }
+
         /// <summary>
         /// Gets the name the assembly file.
         /// </summary>
@@ -280,6 +275,8 @@ namespace MediaBrowser.Common.Plugins
             Configuration = (TConfigurationType)configuration;
 
             SaveConfiguration();
+
+            ConfigurationChanged.Invoke(this, configuration);
         }
 
         /// <inheritdoc />

+ 0 - 12
MediaBrowser.Common/Plugins/IPlugin.cs

@@ -62,18 +62,6 @@ namespace MediaBrowser.Common.Plugins
         /// Called when just before the plugin is uninstalled from the server.
         /// </summary>
         void OnUninstalling();
-
-        /// <summary>
-        /// Registers the plugin's services to the service collection.
-        /// </summary>
-        /// <param name="serviceCollection">The service collection.</param>
-        void RegisterServices(IServiceCollection serviceCollection);
-
-        /// <summary>
-        /// Unregisters the plugin's services from the service collection.
-        /// </summary>
-        /// <param name="serviceCollection">The service collection.</param>
-        void UnregisterServices(IServiceCollection serviceCollection);
     }
 
     public interface IHasPluginConfiguration

+ 19 - 0
MediaBrowser.Common/Plugins/IPluginServiceRegistrator.cs

@@ -0,0 +1,19 @@
+namespace MediaBrowser.Common.Plugins
+{
+    using Microsoft.Extensions.DependencyInjection;
+
+    /// <summary>
+    /// Defines the <see cref="IPluginServiceRegistrator" />.
+    /// </summary>
+    public interface IPluginServiceRegistrator
+    {
+        /// <summary>
+        /// Registers the plugin's services with the service collection.
+        /// </summary>
+        /// <remarks>
+        /// This interface is only used for service registration and requires a parameterless constructor.
+        /// </remarks>
+        /// <param name="serviceCollection">The service collection.</param>
+        void RegisterServices(IServiceCollection serviceCollection);
+    }
+}