mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Allows Loading both IPlugin and IAsyncPlugin
This commit is contained in:
parent
3cd609377e
commit
b8f7d89970
3 changed files with 61 additions and 58 deletions
|
|
@ -20,7 +20,7 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
dependencyResolver = new AssemblyDependencyResolver(assemblyFilePath);
|
dependencyResolver = new AssemblyDependencyResolver(assemblyFilePath);
|
||||||
assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyFilePath));
|
assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyFilePath));
|
||||||
|
|
||||||
referencedPluginPackageDependencyResolver =
|
referencedPluginPackageDependencyResolver =
|
||||||
new AssemblyDependencyResolver(Path.Combine(Constant.ProgramDirectory, "Flow.Launcher.Plugin.dll"));
|
new AssemblyDependencyResolver(Path.Combine(Constant.ProgramDirectory, "Flow.Launcher.Plugin.dll"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,15 +38,15 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
// that use Newtonsoft.Json
|
// that use Newtonsoft.Json
|
||||||
if (assemblyPath == null || ExistsInReferencedPluginPackage(assemblyName))
|
if (assemblyPath == null || ExistsInReferencedPluginPackage(assemblyName))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -54,4 +54,4 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
return referencedPluginPackageDependencyResolver.ResolveAssemblyToPath(assemblyName) != null;
|
return referencedPluginPackageDependencyResolver.ResolveAssemblyToPath(assemblyName) != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue