diff options
author | vnugent <public@vaughnnugent.com> | 2023-01-09 15:09:13 -0500 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2023-01-09 15:09:13 -0500 |
commit | a46c3bf452d287b50b2e7dd5a24f5995c9fd26f6 (patch) | |
tree | 3a978b2dd2887b5c0e25f595516594a647d8e880 /VNLib.Plugins.Extensions.Loading/AssemblyLoader.cs | |
parent | 189c6714057bf45553847eaeb9ce97eb7272eb8c (diff) |
Restructure
Diffstat (limited to 'VNLib.Plugins.Extensions.Loading/AssemblyLoader.cs')
-rw-r--r-- | VNLib.Plugins.Extensions.Loading/AssemblyLoader.cs | 162 |
1 files changed, 0 insertions, 162 deletions
diff --git a/VNLib.Plugins.Extensions.Loading/AssemblyLoader.cs b/VNLib.Plugins.Extensions.Loading/AssemblyLoader.cs deleted file mode 100644 index 5baf123..0000000 --- a/VNLib.Plugins.Extensions.Loading/AssemblyLoader.cs +++ /dev/null @@ -1,162 +0,0 @@ -/* -* Copyright (c) 2022 Vaughn Nugent -* -* Library: VNLib -* Package: VNLib.Plugins.Extensions.Loading -* File: AssemblyLoader.cs -* -* AssemblyLoader.cs is part of VNLib.Plugins.Extensions.Loading which is part of the larger -* VNLib collection of libraries and utilities. -* -* VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published -* by the Free Software Foundation, either version 2 of the License, -* or (at your option) any later version. -* -* VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with VNLib.Plugins.Extensions.Loading. If not, see http://www.gnu.org/licenses/. -*/ - -using System; -using System.Linq; -using System.Threading; -using System.Reflection; -using System.Runtime.Loader; -using System.Collections.Generic; - -using McMaster.NETCore.Plugins; - -using VNLib.Utils.Resources; - -namespace VNLib.Plugins.Extensions.Loading -{ - /// <summary> - /// <para> - /// Represents a disposable assembly loader wrapper for - /// exporting a signle type from a loaded assembly - /// </para> - /// <para> - /// If the loaded type implements <see cref="IDisposable"/> the - /// dispose method is called when the loader is disposed - /// </para> - /// </summary> - /// <typeparam name="T">The exported type to manage</typeparam> - public class AssemblyLoader<T> : OpenResourceHandle<T> - { - private readonly PluginLoader _loader; - private readonly CancellationTokenRegistration _reg; - private readonly Lazy<T> _instance; - - /// <summary> - /// The instance of the loaded type - /// </summary> - public override T Resource => _instance.Value; - - private AssemblyLoader(PluginLoader loader, in CancellationToken unloadToken) - { - _loader = loader; - //Init lazy loader - _instance = new(LoadAndGetExportedType, LazyThreadSafetyMode.PublicationOnly); - //Register dispose - _reg = unloadToken.Register(Dispose); - } - - /// <summary> - /// Loads the default assembly and gets the expected export type, - /// creates a new instance, and calls its parameterless constructor - /// </summary> - /// <returns>The desired type instance</returns> - /// <exception cref="EntryPointNotFoundException"></exception> - private T LoadAndGetExportedType() - { - //Load the assembly - Assembly asm = _loader.LoadDefaultAssembly(); - - Type resourceType = typeof(T); - - //See if the type is exported - Type exp = (from type in asm.GetExportedTypes() - where resourceType.IsAssignableFrom(type) - select type) - .FirstOrDefault() - ?? throw new EntryPointNotFoundException($"Imported assembly does not export desired type {resourceType.FullName}"); - //Create instance - return (T)Activator.CreateInstance(exp)!; - } - - /// <summary> - /// Creates a method delegate for the given method name from - /// the instance wrapped by the current loader - /// </summary> - /// <typeparam name="TDelegate"></typeparam> - /// <param name="methodName">The name of the method to recover</param> - /// <returns>The delegate method wrapper if found, null otherwise</returns> - /// <exception cref="ArgumentNullException"></exception> - /// <exception cref="AmbiguousMatchException"></exception> - public TDelegate? TryGetMethod<TDelegate>(string methodName) where TDelegate : Delegate - { - //get the type info of the actual resource - return Resource!.GetType() - .GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance) - ?.CreateDelegate<TDelegate>(Resource); - } - - ///<inheritdoc/> - protected override void Free() - { - //If the instance is disposable, call its dispose method on unload - if (_instance.IsValueCreated && _instance.Value is IDisposable) - { - (_instance.Value as IDisposable)?.Dispose(); - } - _loader.Dispose(); - _reg.Dispose(); - } - - /// <summary> - /// Creates a new assembly loader for the specified type and - /// </summary> - /// <param name="assemblyName">The name of the assmbly within the current plugin directory</param> - /// <param name="unloadToken">The plugin unload token</param> - internal static AssemblyLoader<T> Load(string assemblyName, CancellationToken unloadToken) - { - Assembly executingAsm = Assembly.GetExecutingAssembly(); - AssemblyLoadContext currentCtx = AssemblyLoadContext.GetLoadContext(executingAsm) ?? throw new InvalidOperationException("Could not get default assembly load context"); - - List<Type> shared = new () - { - typeof(T), - typeof(PluginBase), - }; - - //Share all VNLib internal libraries - shared.AddRange(currentCtx.Assemblies.Where(static s => s.FullName.Contains("VNLib", StringComparison.OrdinalIgnoreCase)).SelectMany(static s => s.GetExportedTypes())); - - PluginLoader loader = PluginLoader.CreateFromAssemblyFile(assemblyName, - currentCtx.IsCollectible, - shared.ToArray(), - conf => - { - - /* - * Load context is required to be set to the executing assembly's load context - * because it is controlled by the host, so this loader should be considered a - * a "child" collection of assemblies - */ - conf.DefaultContext = currentCtx; - - conf.PreferSharedTypes = true; - - //Share utils asm - conf.SharedAssemblies.Add(typeof(Utils.Memory.Memory).Assembly.GetName()); - }); - - return new(loader, in unloadToken); - } - } -} |