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

@ -20,7 +20,7 @@ namespace Flow.Launcher.Core.Plugin
dependencyResolver = new AssemblyDependencyResolver(assemblyFilePath);
assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyFilePath));
referencedPluginPackageDependencyResolver =
referencedPluginPackageDependencyResolver =
new AssemblyDependencyResolver(Path.Combine(Constant.ProgramDirectory, "Flow.Launcher.Plugin.dll"));
}
@ -38,15 +38,15 @@ namespace Flow.Launcher.Core.Plugin
// that use Newtonsoft.Json
if (assemblyPath == null || ExistsInReferencedPluginPackage(assemblyName))
return null;
return LoadFromAssemblyPath(assemblyPath);
}
internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type)
internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, params Type[] types)
{
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)
@ -54,4 +54,4 @@ namespace Flow.Launcher.Core.Plugin
return referencedPluginPackageDependencyResolver.ResolveAssemblyToPath(assemblyName) != null;
}
}
}
}

View file

@ -37,56 +37,59 @@ namespace Flow.Launcher.Core.Plugin
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
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);
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);
}
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);
}
try
{
var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
assembly = assemblyLoader.LoadAssemblyAndDependencies();
if (plugin == null)
{
erroredPlugins.Add(metadata.Name);
return;
}
var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin),
typeof(IAsyncPlugin));
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
plugins.Add(new PluginPair
{
Plugin = plugin,
Metadata = metadata
plugins.Add(new PluginPair
{
Plugin = plugin,
Metadata = metadata
});
});
});
metadata.InitTime += milliseconds;
}
@ -95,15 +98,15 @@ namespace Flow.Launcher.Core.Plugin
var errorPluginString = String.Join(Environment.NewLine, erroredPlugins);
var errorMessage = "The following "
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
+ "errored and cannot be loaded:";
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
+ "errored and cannot be loaded:";
Task.Run(() =>
{
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
$"Please refer to the logs for more information","",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
$"Please refer to the logs for more information", "",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
});
}
@ -179,6 +182,5 @@ namespace Flow.Launcher.Core.Plugin
Metadata = metadata
});
}
}
}

View file

@ -417,7 +417,7 @@ namespace Flow.Launcher.ViewModel
{
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
});
@ -438,10 +438,11 @@ namespace Flow.Launcher.ViewModel
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);
UpdateResultView(result, plugins[pairIndex].Metadata, query);
var results = await PluginManager.QueryForPlugin(plugin, query, token);
UpdateResultView(results, plugin.Metadata, query);
}
}, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),