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); } } }