using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; // ReSharper disable InconsistentNaming namespace Barotrauma.LuaCs.Services; public interface IAssemblyManagementService : IService { #region Public API /// /// Called when an assembly is loaded. /// public event Action OnAssemblyLoaded; /// /// Called when an assembly is marked for unloading, before unloading begins. You should use this to cleanup /// any references that you have to this assembly. /// public event Action OnAssemblyUnloading; /// /// Called whenever an exception is thrown. First arg is a formatted message, Second arg is the Exception. /// public event Action OnException; /// /// For unloading issue debugging. Called whenever MemoryFileAssemblyContextLoader [load context] is unloaded. /// // ReSharper disable once InconsistentNaming public event Action OnACLUnload; /// /// [DEBUG ONLY] /// Returns a list of the current unloading ACLs. /// // ReSharper disable once InconsistentNaming public ImmutableList> StillUnloadingACLs { get; } // ReSharper disable once MemberCanBePrivate.Global /// /// Checks if there are any AssemblyLoadContexts still in the process of unloading. /// public bool IsCurrentlyUnloading { get; } /// /// Allows iteration over all non-interface types in all loaded assemblies in the AsmMgr that are assignable to the given type (IsAssignableFrom). /// Warning: care should be used when using this method in hot paths as performance may be affected. /// /// The type to compare against /// Forces caches to clear and for the lists of types to be rebuilt. /// An Enumerator for matching types. public IEnumerable GetSubTypesInLoadedAssemblies(bool rebuildList); /// /// Tries to get types assignable to type from the ACL given the Guid. /// /// /// /// /// Operation success. public bool TryGetSubTypesFromACL(Guid id, out IEnumerable types); /// /// Tries to get types from the ACL given the Guid. /// /// /// /// public bool TryGetSubTypesFromACL(Guid id, out IEnumerable types); /// /// Allows iteration over all types, including interfaces, in all loaded assemblies in the AsmMgr who's names match the string. /// Note: Will return the by-reference equivalent type if the type name is prefixed with "out " or "ref ". /// /// The string name of the type to search for. /// An Enumerator for matching types. List will be empty if bad params are supplied. public IEnumerable GetTypesByName(string typeName); /// /// Allows iteration over all types (including interfaces) in all loaded assemblies managed by the AsmMgr. /// Warning: High usage may result in performance issues. /// /// An Enumerator for iteration. public IEnumerable GetAllTypesInLoadedAssemblies(); /// /// Returns a list of all loaded ACLs. /// WARNING: References to these ACLs outside the AssemblyManager should be kept in a WeakReference in order /// to avoid causing issues with unloading/disposal. /// /// public IEnumerable GetAllLoadedACLs(); #endregion #region InternalAPI /*** Notes: Internal API uses the 'public' modifier because of the common and recommended use of publicized APIs * by third-party add-ins. */ /// /// [Unsafe] Warning: only for use in nested threading functions. Requires care to manage access. /// Does not make any guarantees about the state of the ACL after the list has been returned. /// /// public ImmutableList UnsafeGetAllLoadedACLs(); /// /// Used by content package and plugin management to stop unloading of a given ACL until all plugins have gracefully closed. /// public event System.Func IsReadyToUnloadACL; /// /// Compiles an assembly from supplied references and syntax trees into the specified AssemblyContextLoader. /// A new ACL will be created if the Guid supplied is Guid.Empty. /// /// /// /// /// /// A non-unique name for later reference. Optional, set to null if unused. /// The guid of the assembly /// /// public AssemblyLoadingSuccessState LoadAssemblyFromMemory([NotNull] string compiledAssemblyName, [NotNull] IEnumerable syntaxTree, IEnumerable externalMetadataReferences, [NotNull] CSharpCompilationOptions compilationOptions, string friendlyName, ref Guid id, IEnumerable externFileAssemblyRefs = null); /// /// Switches the ACL with the given Guid to Template Mode, which disables assembly name resolution for any assemblies loaded in it. /// These ACLs are intended to be used to host Assemblies for information only and not for code execution. /// WARNING: This process is irreversible. /// /// Guid of the ACL. /// Whether an ACL was found with the given ID. public bool SetACLToTemplateMode(Guid guid); /// /// Tries to load all assemblies at the supplied file paths list into the ACl with the given Guid. /// If the supplied Guid is Empty, then a new ACl will be created and the Guid will be assigned to it. /// /// List of assemblies to try and load. /// A non-unique name for later reference. Optional. /// Guid of the ACL or Empty if none specified. Guid of ACL will be assigned to this var. /// Operation success messages. /// public AssemblyLoadingSuccessState LoadAssembliesFromLocations([NotNull] IEnumerable filePaths, string friendlyName, ref Guid id); /// /// Tries to begin the disposal process of ACLs. /// /// Returns whether the unloading process could be initiated. public bool TryBeginDispose(); /// /// Returns whether unloading is completed and updates the styate of the unloading cache. /// /// public bool FinalizeDispose(); /// /// Tries to retrieve the LoadedACL with the given ID or null if none is found. /// WARNING: External references to this ACL with long lifespans should be kept in a WeakReference /// to avoid causing unloading/disposal issues. /// /// GUID of the ACL. /// The found ACL or null if none was found. /// Whether an ACL was found. public bool TryGetACL(Guid id, out AssemblyManager.LoadedACL acl); #endregion }