Allows Loading both IPlugin and IAsyncPlugin

This commit is contained in:
张弘韬 2021-01-02 17:25:13 +08:00 committed by 弘韬 张
parent 3cd609377e
commit b8f7d89970
3 changed files with 61 additions and 58 deletions

View file

@ -42,11 +42,11 @@ namespace Flow.Launcher.Core.Plugin
return LoadFromAssemblyPath(assemblyPath); return LoadFromAssemblyPath(assemblyPath);
} }
internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type) internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, params Type[] types)
{ {
var allTypes = assembly.ExportedTypes; var allTypes = assembly.ExportedTypes;
return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(type)); return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Intersect(types).Any());
} }
internal bool ExistsInReferencedPluginPackage(AssemblyName assemblyName) internal bool ExistsInReferencedPluginPackage(AssemblyName assemblyName)

View file

@ -37,56 +37,59 @@ namespace Flow.Launcher.Core.Plugin
foreach (var metadata in metadatas) foreach (var metadata in metadatas)
{ {
var milliseconds = Stopwatch.Debug($"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () => var milliseconds = Stopwatch.Debug(
{ $"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () =>
{
#if DEBUG #if DEBUG
var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
var assembly = assemblyLoader.LoadAssemblyAndDependencies();
var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin));
var plugin = (IPlugin)Activator.CreateInstance(type);
#else
Assembly assembly = null;
IPlugin plugin = null;
try
{
var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath); var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
assembly = assemblyLoader.LoadAssemblyAndDependencies(); var assembly = assemblyLoader.LoadAssemblyAndDependencies();
var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin),
typeof(IAsyncPlugin));
var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin)); var plugin = Activator.CreateInstance(type);
#else
Assembly assembly = null;
IPlugin plugin = null;
plugin = (IPlugin)Activator.CreateInstance(type); try
} {
catch (Exception e) when (assembly == null) var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
{ assembly = assemblyLoader.LoadAssemblyAndDependencies();
Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
}
catch (InvalidOperationException e)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
}
catch (ReflectionTypeLoadException e)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
}
catch (Exception e)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
}
if (plugin == null) var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin),
{ typeof(IAsyncPlugin));
erroredPlugins.Add(metadata.Name);
return; plugin = Activator.CreateInstance(type);
} }
catch (Exception e) when (assembly == null)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
}
catch (InvalidOperationException e)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
}
catch (ReflectionTypeLoadException e)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
}
catch (Exception e)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
}
if (plugin == null)
{
erroredPlugins.Add(metadata.Name);
return;
}
#endif #endif
plugins.Add(new PluginPair plugins.Add(new PluginPair
{ {
Plugin = plugin, Plugin = plugin,
Metadata = metadata Metadata = metadata
});
}); });
});
metadata.InitTime += milliseconds; metadata.InitTime += milliseconds;
} }
@ -95,15 +98,15 @@ namespace Flow.Launcher.Core.Plugin
var errorPluginString = String.Join(Environment.NewLine, erroredPlugins); var errorPluginString = String.Join(Environment.NewLine, erroredPlugins);
var errorMessage = "The following " var errorMessage = "The following "
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ") + (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
+ "errored and cannot be loaded:"; + "errored and cannot be loaded:";
Task.Run(() => Task.Run(() =>
{ {
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
$"Please refer to the logs for more information","", $"Please refer to the logs for more information", "",
MessageBoxButtons.OK, MessageBoxIcon.Warning); MessageBoxButtons.OK, MessageBoxIcon.Warning);
}); });
} }
@ -179,6 +182,5 @@ namespace Flow.Launcher.Core.Plugin
Metadata = metadata Metadata = metadata
}); });
} }
} }
} }

View file

@ -417,7 +417,7 @@ namespace Flow.Launcher.ViewModel
{ {
if (!plugins[i].Metadata.Disabled) if (!plugins[i].Metadata.Disabled)
{ {
tasks[i] = QueryTask(i, query, currentCancellationToken); tasks[i] = QueryTask(plugins[i], query, currentCancellationToken);
} }
else tasks[i] = Task.CompletedTask; // Avoid Null else tasks[i] = Task.CompletedTask; // Avoid Null
}); });
@ -438,10 +438,11 @@ namespace Flow.Launcher.ViewModel
ProgressBarVisibility = Visibility.Hidden; ProgressBarVisibility = Visibility.Hidden;
} }
async Task QueryTask(int pairIndex, Query query, CancellationToken token) // Local Function
async Task QueryTask(PluginPair plugin, Query query, CancellationToken token)
{ {
var result = await PluginManager.QueryForPlugin(plugins[pairIndex], query, token); var results = await PluginManager.QueryForPlugin(plugin, query, token);
UpdateResultView(result, plugins[pairIndex].Metadata, query); UpdateResultView(results, plugin.Metadata, query);
} }
}, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception), }, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),