using System.Reflection;
using AcDream.Plugin.Abstractions;
namespace AcDream.Core.Plugins;
public static class PluginLoader
{
///
/// Load a plugin DLL from into a collectible
/// , find the first type
/// implementing , instantiate it, and call its
/// with the supplied host. Any failure
/// is returned as a failed rather than thrown.
///
public static LoadedPlugin Load(string pluginDirectory, PluginManifest manifest, IPluginHost host)
{
var dllPath = Path.Combine(pluginDirectory, manifest.EntryDll);
if (!File.Exists(dllPath))
return new LoadedPlugin(
manifest,
Plugin: null,
LoadContext: null,
Error: new FileNotFoundException($"entry dll not found: {dllPath}", dllPath));
try
{
var alc = new PluginAssemblyLoadContext(pluginDirectory, dllPath);
var asm = alc.LoadFromAssemblyPath(dllPath);
IEnumerable types;
try
{
types = asm.GetTypes();
}
catch (ReflectionTypeLoadException rtle)
{
types = rtle.Types.OfType();
}
var pluginType = types
.FirstOrDefault(t => !t.IsAbstract && typeof(IAcDreamPlugin).IsAssignableFrom(t));
if (pluginType is null)
return new LoadedPlugin(
manifest,
Plugin: null,
LoadContext: null,
Error: new InvalidOperationException(
$"no IAcDreamPlugin implementation found in {manifest.EntryDll}"));
var instance = (IAcDreamPlugin)Activator.CreateInstance(pluginType)!;
instance.Initialize(host);
return new LoadedPlugin(manifest, instance, alc, Error: null);
}
catch (Exception ex)
{
return new LoadedPlugin(manifest, Plugin: null, LoadContext: null, Error: ex);
}
}
}