Skip to content

Commit

Permalink
breaking change: plugins run from the "plugins" subfolder
Browse files Browse the repository at this point in the history
reason: this allows to run without publishing the app as a single file, which at the time of writing allows to workaround dotnet/runtime#59961
  • Loading branch information
freddyrios committed Oct 5, 2021
1 parent 9e1fae4 commit d9d8647
Showing 1 changed file with 27 additions and 28 deletions.
55 changes: 27 additions & 28 deletions CA_DataUploaderLib/PluginsLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ public PluginsLoader(CommandHandler handler, Func<(string pluginName, string tar

public void LoadPlugins(bool automaticallyLoadPluginChanges = true)
{
Directory.CreateDirectory("plugins");
// load all
foreach (var assembly in Directory.GetFiles(".", "*.dll"))
LoadPlugin(assembly);
foreach (var assemblyFullPath in Directory.GetFiles("plugins", "*.dll"))
LoadPlugin(assemblyFullPath);

if (automaticallyLoadPluginChanges)
{
_pluginChangesWatcher = new SingleFireFileWatcher(".", "*.dll");
_pluginChangesWatcher = new SingleFireFileWatcher("plugins", "*.dll");
_pluginChangesWatcher.Deleted += UnloadPlugin;
_pluginChangesWatcher.Changed += ReloadPlugin;
}
Expand All @@ -49,10 +50,9 @@ public void UnloadPlugins()
GC.Collect(); // triggers the unload of the assembly (after DoUnloadExtension we no longer have references to the instances)
}

void LoadPlugin(string assemblyPath)
void LoadPlugin(string assemblyFullPath)
{
assemblyPath = Path.GetFullPath(assemblyPath);
var (context, plugins) = Load(assemblyPath, plugingArgs);
var (context, plugins) = Load(assemblyFullPath, plugingArgs);
var initializedPlugins = plugins.ToList();
if (initializedPlugins.Count == 0)
{
Expand All @@ -63,26 +63,25 @@ void LoadPlugin(string assemblyPath)
foreach (var plugin in initializedPlugins)
plugin.Initialize(new PluginsCommandHandler(handler), new PluginsLogger(plugin.Name));

_runningPlugins[assemblyPath] = (context, initializedPlugins);
CALog.LogData(LogID.A, $"loaded plugins from {assemblyPath} - {string.Join(",", initializedPlugins.Select(e => e.GetType().Name))}");
_runningPlugins[assemblyFullPath] = (context, initializedPlugins);
CALog.LogData(LogID.A, $"loaded plugins from {assemblyFullPath} - {string.Join(",", initializedPlugins.Select(e => e.GetType().Name))}");
}

void UnloadPlugin(string assemblyPath)
void UnloadPlugin(string assemblyFullPath)
{
assemblyPath = Path.GetFullPath(assemblyPath);
if (!_runningPlugins.TryGetValue(assemblyPath, out var runningPluginEntry))
CALog.LogData(LogID.A, $"running plugin not found: {Path.GetFileNameWithoutExtension(assemblyPath)}");
if (!_runningPlugins.TryGetValue(assemblyFullPath, out var runningPluginEntry))
CALog.LogData(LogID.A, $"running plugin not found: {Path.GetFileNameWithoutExtension(assemblyFullPath)}");
else
UnloadPlugin(assemblyPath, runningPluginEntry);
UnloadPlugin(assemblyFullPath, runningPluginEntry);
}

void UnloadPlugin(string assemblyPath, (AssemblyLoadContext ctx, IEnumerable<LoopControlCommand> instances) entry)
void UnloadPlugin(string assemblyFullPath, (AssemblyLoadContext ctx, IEnumerable<LoopControlCommand> instances) entry)
{
foreach (var instance in entry.instances)
instance.Dispose();
_runningPlugins.Remove(assemblyPath);
_runningPlugins.Remove(assemblyFullPath);
entry.ctx.Unload();
CALog.LogData(LogID.A, $"unloaded plugins from {assemblyPath}");
CALog.LogData(LogID.A, $"unloaded plugins from {assemblyFullPath}");
}

/// <remarks>
Expand All @@ -94,16 +93,16 @@ void ReloadPlugin(string fullpath)
LoadPlugin(fullpath);
}

static (AssemblyLoadContext context, IEnumerable<LoopControlCommand> plugins) Load(string assemblyPath, params object[] args)
static (AssemblyLoadContext context, IEnumerable<LoopControlCommand> plugins) Load(string assemblyFullPath, params object[] args)
{
var (context, assembly) = LoadAssembly(assemblyPath);
var (context, assembly) = LoadAssembly(assemblyFullPath);
return (context, CreateInstances<LoopControlCommand>(assembly, args));
}

static (AssemblyLoadContext context, Assembly assembly) LoadAssembly(string assemblyPath)
static (AssemblyLoadContext context, Assembly assembly) LoadAssembly(string assemblyFullPath)
{
PluginLoadContext context = new PluginLoadContext(assemblyPath);
using var fs = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read); // force no file lock
PluginLoadContext context = new PluginLoadContext(assemblyFullPath);
using var fs = new FileStream(assemblyFullPath, FileMode.Open, FileAccess.Read); // force no file lock
return (context, context.LoadFromStream(fs));
}

Expand All @@ -121,8 +120,8 @@ private class PluginLoadContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver _resolver;

public PluginLoadContext(string pluginPath) : base (true) =>
_resolver = new AssemblyDependencyResolver(pluginPath);
public PluginLoadContext(string pluginFullPath) : base (true) =>
_resolver = new AssemblyDependencyResolver(pluginFullPath);

protected override Assembly Load(AssemblyName assemblyName)
{
Expand Down Expand Up @@ -201,7 +200,7 @@ private async Task UpdateAllPlugins()
foreach (var pluginName in loader.GetRunningPluginsNames())
{
CALog.LogInfoAndConsoleLn(LogID.A, $"downloading plugin: {pluginName}");
await pluginDownloader((pluginName, "."));
await pluginDownloader((pluginName, "plugins"));
}

CALog.LogInfoAndConsoleLn(LogID.A, $"unloading running plugins");
Expand All @@ -214,12 +213,12 @@ private async Task UpdateAllPlugins()
private async Task UpdatePlugin(string pluginName)
{
CALog.LogInfoAndConsoleLn(LogID.A, $"downloading plugin: {pluginName}");
await pluginDownloader((pluginName, "."));
var assemblyPath = Path.GetFullPath(pluginName + ".dll");
await pluginDownloader((pluginName, "plugins"));
var assemblyFullPath = Path.Combine("plugins", Path.GetFullPath(pluginName + ".dll"));
CALog.LogInfoAndConsoleLn(LogID.A, $"unloading plugin: {pluginName}");
loader.UnloadPlugin(assemblyPath);
loader.UnloadPlugin(assemblyFullPath);
CALog.LogInfoAndConsoleLn(LogID.A, $"loading plugin: {pluginName}");
loader.LoadPlugin(assemblyPath);
loader.LoadPlugin(assemblyFullPath);
CALog.LogInfoAndConsoleLn(LogID.A, $"plugins updated");
}
}
Expand Down

1 comment on commit d9d8647

@lasse-tarp-CA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice ide

Please sign in to comment.