using System; using System.Collections.Generic; using System.Drawing; using JD.Kernel.Classes; using JD.Kernel.StaticHelpers; using JD.LogService; using JD.TeaBoxAddinSystem.Addins.Description; using JD.TeaBoxAddinSystem.Addins.Description.Conditions; using JD.TeaBoxAddinSystem.Addins.Internal; namespace JD.TeaBoxAddinSystem.Addins { /// /// Addin Manager. /// public static class AddinManager { private static readonly object m_lock = new object(); private static readonly AddinSessionService m_sessionService = new AddinSessionService(); private static readonly List m_loggers = new List(); private static Implementation m_implementation = new Implementation(); /// /// Loggers can listen to addin events as well as addin loading errors. /// public static IList Loggers { get { return m_loggers; } } /// /// Loaded addins. /// public static ICollection LoadedAddins { get { return SessionService.LoadedAddins; } } /// /// Loaded Extension Type Sets. /// public static IReadOnlyDictionary ExtensionTypeSets { get { return SessionService.ExtensionTypeSets; } } /// /// Loaded Condition Types. /// public static IReadOnlyDictionary ConditionTypes { get { return SessionService.ConditionTypes; } } /// /// Loaded extension points. /// public static IReadOnlyDictionary ExtensionPoints { get { return SessionService.ExtensionPoints; } } /// /// Extension tree. /// public static TreeNode ExtensionTree { get { return SessionService.ExtensionTree; } } internal static AddinSessionService SessionService { get { return m_sessionService; } } static AddinManager() { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } /// /// Returns whether the given is loaded. /// /// /// public static bool IsAddinLoaded(Addin addin) { return SessionService.IsAddinLoaded(addin); } /// /// Returns whether the given is loaded. /// /// /// public static bool IsModuleLoaded(Module module) { return SessionService.IsModuleLoaded(module); } /// /// Loads the given . /// /// public static bool LoadAddin(Addin addin) { return SessionService.LoadAddin(addin); } /// /// Unloads the given . /// /// public static bool UnloadAddin(Addin addin) { return SessionService.UnloadAddin(addin); } /// /// Unloads all the loaded s. /// public static void UnloadAllAddins() { UnloadAllAddins(false); } /// /// Unloads all the loaded s. Used for tests mostly. /// /// Whether to destroy event handlers. public static void UnloadAllAddins(bool destroyHandlers) { SessionService.UnloadAllAddins(destroyHandlers); } /// /// This method will reevaluate all the loaded s. /// /// /// Call this periodically in your application. The more frequent the better but /// there's a performance cost associated with it. /// public static void ReevaluatePolledConditionNodes() { SessionService.ConditionManager.ReevaluatePolledConditionNodes(); } /// /// Gets an extension node at the given . /// /// /// public static ExtensionNode GetExtensionNode(string path) { TreeNode node = ExtensionTree[path]; if (node == null) { return null; } return node.ExtensionNode; } /// /// Gets a list of extension nodes at the given with type . /// /// /// This method returns only the objects of type and ignores other nodes. /// /// Type of extension nodes. /// /// A non null list of extension nodes of type . List may be empty if the path does not exist. public static IEnumerable GetExtensionNodes(string path) where T : ExtensionNode { return m_implementation.GetExtensionNodes(path); } /// /// Gets a list of extension objects at a given . /// /// /// Returns an empty collection when path does not exists. /// /// /// /// public static IList GetExtensionObjects(string path) { return m_implementation.GetExtensionObjects(path); } /// /// Creates a new list of extension objects from the given . /// /// /// This method returns only the objects of type and ignores other created objects. /// /// /// /// public static IEnumerable CreateExtensionObjects(string path) where T : class { ExtensionNode node = GetExtensionNode(path); if (node == null) { yield break; } foreach (ExtensionNode childNode in node.ChildNodes) { object extensionObject = childNode.CreateExtensionObject(); if (!(extensionObject is T)) { throw new ArgumentException( $"Extension node {childNode.FullPath} created object {extensionObject} which is not of the expected type {typeof(T).Name}"); } yield return (T)extensionObject; } } /// /// Registers the given on the at the given . /// /// /// public static void AddExtensionChangedHandler(string path, EventHandler handler) { SessionService.AddExtensionChangedHandler(path, handler); } /// /// Unregisters the given on the at the given . /// /// /// public static void RemoveExtensionChangedHandler(string path, EventHandler handler) { SessionService.RemoveExtensionChangedHandler(path, handler); } /// /// For testing purposes, let swap the implementation. /// public static IDisposable UseMockImplementation(Implementation implementation) { Throw.IfNull(implementation, "implementation"); m_implementation = implementation; return new DisposableHelper(delegate { m_implementation = new Implementation(); }); } public static Image GetImage(string imageName) { return m_implementation.GetImage(imageName); } internal static void Log(LogEvent @event) { m_loggers.ForEach(logger => logger.Log(@event)); } private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { return SessionService.GetAssembly(args.Name); } } }