From ab7d00eacc9a7e18014e03999db0968567471d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 23 Mar 2021 17:25:46 +0800 Subject: [PATCH 1/2] Make IPlugin inherit from IAsyncPlugin --- .../Plugin/PluginAssemblyLoader.cs | 4 +-- Flow.Launcher.Core/Plugin/PluginManager.cs | 31 +++++-------------- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 24 +++++++------- Flow.Launcher.Plugin/IAsyncPlugin.cs | 2 +- Flow.Launcher.Plugin/IPlugin.cs | 8 ++++- Flow.Launcher.Plugin/PluginPair.cs | 2 +- 6 files changed, 30 insertions(+), 41 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs b/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs index f473cbc65..e18985fe7 100644 --- a/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs @@ -49,10 +49,10 @@ namespace Flow.Launcher.Core.Plugin return LoadFromAssemblyPath(assemblyPath); } - internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, params Type[] types) + internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type) { var allTypes = assembly.ExportedTypes; - return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Intersect(types).Any()); + return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Any(t => t == type)); } internal bool ExistsInReferencedPackage(AssemblyName assemblyName) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 66eb0f0ec..8c9fd2eb9 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -97,16 +97,9 @@ namespace Flow.Launcher.Core.Plugin { try { - var milliseconds = pair.Plugin switch - { - IAsyncPlugin plugin - => await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", - () => plugin.InitAsync(new PluginInitContext(pair.Metadata, API))), - IPlugin plugin - => Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", - () => plugin.Init(new PluginInitContext(pair.Metadata, API))), - _ => throw new ArgumentException(), - }; + var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", + () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API))); + pair.Metadata.InitTime += milliseconds; Log.Info( $"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>"); @@ -169,19 +162,9 @@ namespace Flow.Launcher.Core.Plugin long milliseconds = -1L; - switch (pair.Plugin) - { - case IAsyncPlugin plugin: - milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", - async () => results = await plugin.QueryAsync(query, token).ConfigureAwait(false)); - break; - case IPlugin plugin: - await Task.Run(() => milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", - () => results = plugin.Query(query)), token).ConfigureAwait(false); - break; - default: - throw new ArgumentOutOfRangeException(); - } + milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", + async () => results = await pair.Plugin.QueryAsync(query, token).ConfigureAwait(false)); + token.ThrowIfCancellationRequested(); if (results == null) return results; @@ -199,7 +182,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e); + Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e); } return results; diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 2c75f9633..92aca8109 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -44,23 +44,23 @@ namespace Flow.Launcher.Core.Plugin #if DEBUG var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath); var assembly = assemblyLoader.LoadAssemblyAndDependencies(); - var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin), + var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IAsyncPlugin)); - var plugin = Activator.CreateInstance(type); + var plugin = Activator.CreateInstance(type) as IAsyncPlugin; #else Assembly assembly = null; - object plugin = null; + IAsyncPlugin plugin = null; try { var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath); assembly = assemblyLoader.LoadAssemblyAndDependencies(); - var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin), + var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IAsyncPlugin)); - plugin = Activator.CreateInstance(type); + plugin = Activator.CreateInstance(type) as IAsyncPlugin; } catch (Exception e) when (assembly == null) { @@ -78,13 +78,13 @@ namespace Flow.Launcher.Core.Plugin { Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e); } - +#endif if (plugin == null) { erroredPlugins.Add(metadata.Name); return; } -#endif + plugins.Add(new PluginPair { Plugin = plugin, @@ -139,7 +139,7 @@ namespace Flow.Launcher.Core.Plugin } else { - Log.Error("PluginsLoader","Failed to set Python path despite the environment variable PATH is found", "PythonPlugins"); + Log.Error("PluginsLoader", "Failed to set Python path despite the environment variable PATH is found", "PythonPlugins"); } } } @@ -152,7 +152,7 @@ namespace Flow.Launcher.Core.Plugin } else { - Log.Error("PluginsLoader",$"Tried to automatically set from Settings.PythonDirectory " + + Log.Error("PluginsLoader", $"Tried to automatically set from Settings.PythonDirectory " + $"but can't find python executable in {path}", "PythonPlugins"); } } @@ -205,7 +205,7 @@ namespace Flow.Launcher.Core.Plugin } else { - Log.Error("PluginsLoader", + Log.Error("PluginsLoader", $"Failed to set Python path after Droplex install, {pythonPath} does not exist", "PythonPlugins"); } @@ -215,8 +215,8 @@ namespace Flow.Launcher.Core.Plugin if (string.IsNullOrEmpty(settings.PythonDirectory)) { MessageBox.Show("Unable to set Python executable path, please try from Flow's settings (scroll down to the bottom)."); - Log.Error("PluginsLoader", - $"Not able to successfully set Python path, the PythonDirectory variable is still an empty string.", + Log.Error("PluginsLoader", + $"Not able to successfully set Python path, the PythonDirectory variable is still an empty string.", "PythonPlugins"); return new List(); diff --git a/Flow.Launcher.Plugin/IAsyncPlugin.cs b/Flow.Launcher.Plugin/IAsyncPlugin.cs index b0b41cc22..3dcb97d99 100644 --- a/Flow.Launcher.Plugin/IAsyncPlugin.cs +++ b/Flow.Launcher.Plugin/IAsyncPlugin.cs @@ -19,7 +19,7 @@ namespace Flow.Launcher.Plugin /// Query to search /// Cancel when querying job is obsolete /// - Task> QueryAsync(Query query, CancellationToken token); + abstract Task> QueryAsync(Query query, CancellationToken token); /// /// Initialize plugin asynchrously (will still wait finish to continue) diff --git a/Flow.Launcher.Plugin/IPlugin.cs b/Flow.Launcher.Plugin/IPlugin.cs index 203dc9af7..bac93d090 100644 --- a/Flow.Launcher.Plugin/IPlugin.cs +++ b/Flow.Launcher.Plugin/IPlugin.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; namespace Flow.Launcher.Plugin { @@ -9,7 +11,7 @@ namespace Flow.Launcher.Plugin /// or performaing CPU intense jobs (performing better with cancellation), please try the IAsyncPlugin interface /// /// - public interface IPlugin + public interface IPlugin : IAsyncPlugin { /// /// Querying when user's search changes @@ -27,5 +29,9 @@ namespace Flow.Launcher.Plugin /// /// void Init(PluginInitContext context); + + Task IAsyncPlugin.InitAsync(PluginInitContext context) => Task.Run(() => Init(context)); + + Task> IAsyncPlugin.QueryAsync(Query query, CancellationToken token) => Task.Run(() => Query(query)); } } diff --git a/Flow.Launcher.Plugin/PluginPair.cs b/Flow.Launcher.Plugin/PluginPair.cs index e8954b7a0..7bf634691 100644 --- a/Flow.Launcher.Plugin/PluginPair.cs +++ b/Flow.Launcher.Plugin/PluginPair.cs @@ -2,7 +2,7 @@ { public class PluginPair { - public object Plugin { get; internal set; } + public IAsyncPlugin Plugin { get; internal set; } public PluginMetadata Metadata { get; internal set; } From 6bbedbaaa16eb00d93f74783922edc045c40882a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 23 Mar 2021 17:55:40 +0800 Subject: [PATCH 2/2] remove the explicitly abstract --- Flow.Launcher.Plugin/IAsyncPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/IAsyncPlugin.cs b/Flow.Launcher.Plugin/IAsyncPlugin.cs index 3dcb97d99..b0b41cc22 100644 --- a/Flow.Launcher.Plugin/IAsyncPlugin.cs +++ b/Flow.Launcher.Plugin/IAsyncPlugin.cs @@ -19,7 +19,7 @@ namespace Flow.Launcher.Plugin /// Query to search /// Cancel when querying job is obsolete /// - abstract Task> QueryAsync(Query query, CancellationToken token); + Task> QueryAsync(Query query, CancellationToken token); /// /// Initialize plugin asynchrously (will still wait finish to continue)