Skip to content

Commit

Permalink
auto resolve library references
Browse files Browse the repository at this point in the history
  • Loading branch information
Rynchodon committed Jul 24, 2017
1 parent d5a894d commit 7051f92
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 20 deletions.
84 changes: 65 additions & 19 deletions PluginLoader/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,37 @@ private bool LoadDll(string relativePath, string[] requiredFiles, ICollection<IP
return false;
}

Assembly assembly = LoadDllAutoResolve(fullPath);

if (assembly == null)
{
LogFailedToLoadFile(fullPath, "could not load assembly");
return false;
}

if (!loaded.Add(relativePath))
throw new Exception(fullPath + " already loaded");

Logger.WriteLine("Loading plugins from " + fullPath);

foreach (Type t in assembly.ExportedTypes)
if (typeof(IPlugin).IsAssignableFrom(t))
{
try { pluginInterface.Add((IPlugin)Activator.CreateInstance(t)); }
catch (Exception ex)
{
LogFailedToLoadFile(fullPath, "exception while creating instance of " + t.FullName + ":\n" + ex);
return false;
}
Logger.WriteLine("Loaded \"" + t.FullName + '"');
}

return true;
}

[Obsolete]
private bool LoadRequiredFiles(string[] requiredFiles, ICollection<IPlugin> pluginInterface, HashSet<string> loaded, int depth, string fullPath)
{
if (requiredFiles != null)
foreach (string fileName in requiredFiles)
{
Expand All @@ -233,31 +264,46 @@ private bool LoadDll(string relativePath, string[] requiredFiles, ICollection<IP
return false;
}
}
return true;
}

if (!loaded.Add(relativePath))
throw new Exception(fullPath + " already loaded");
/// <summary>
/// Try to load an assembly, resolving references from the plugin's directory.
/// </summary>
private Assembly LoadDllAutoResolve(string fullPath)
{
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
try { return TryLoadAssembly(fullPath); }
finally { AppDomain.CurrentDomain.AssemblyResolve -= AssemblyResolve; }
}

Logger.WriteLine("Loading plugins from " + fullPath);
private Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
string name = new AssemblyName(args.Name).Name;
string[] assemblyPath = Directory.GetFiles(directory, name + ".dll", SearchOption.AllDirectories);

Assembly assembly = Assembly.LoadFrom(fullPath);
if (assembly == null)
switch (assemblyPath.Length)
{
LogFailedToLoadFile(fullPath, "could not load assembly");
return false;
case 0:
Logger.WriteLine("No assembly named " + name + " could be located");
return null;
case 1:
Logger.WriteLine("Located assembly " + name + " in " + directory);
return TryLoadAssembly(assemblyPath[0]);
default:
Logger.WriteLine("Multiple files match " + name + ":\n" + string.Join("\n\t", assemblyPath));
return null;
}
foreach (Type t in assembly.ExportedTypes)
if (typeof(IPlugin).IsAssignableFrom(t))
{
try { pluginInterface.Add((IPlugin)Activator.CreateInstance(t)); }
catch (Exception ex)
{
LogFailedToLoadFile(fullPath, "exception while creating instance of " + t.FullName + ":\n" + ex);
return false;
}
Logger.WriteLine("Loaded \"" + t.FullName + '"');
}
}

return true;
private Assembly TryLoadAssembly(string fullPath)
{
try { return Assembly.LoadFrom(fullPath); }
catch (Exception ex)
{
Logger.WriteLine(ex.ToString());
return null;
}
}

private void LogFailedToLoadFile(string fullPath, string reason)
Expand Down
4 changes: 3 additions & 1 deletion PluginLoader/PluginBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
using System;
using System.Runtime.Serialization;

namespace Rynchodon.PluginLoader
{
Expand All @@ -19,6 +20,7 @@ public sealed class File
public string targetFolder;
/// <summary>Names of files in this plugin that must be loaded before this one.</summary>
[DataMember]
[Obsolete("references are resolved automatically")]
public string[] requires;

public File(string source, string targetFolder, string[] requires)
Expand Down

0 comments on commit 7051f92

Please sign in to comment.