using HMI.Core.Api; using HMI.Core.Entity; using HMI.Core.Util; using log4net; using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading; using System.Windows; using System.Windows.Threading; namespace HMI.Base { public enum LoadMsgType { INIT, LOADING, FINISHED } public class LoadMsg { public string Message { get; set; } public bool? Result { get; set; } public LoadMsgType Type { get; set; } public int NumData { get; set; } } public class PluginLoader { private static ILog log = LogManager.GetLogger("PluginLoader"); private static string PluginFolder = PathHelper.PluginFolder(); public SqliteHelper sqliteHelper; public List Menus { get; private set; } public List Plugins { get; private set; } public static PluginLoader Instance { get; private set; } public event EventHandler LoadMessageAppend; private PluginLoader() { sqliteHelper = new SqliteHelper(PathHelper.DatabasePath); } public static void Reset() { if (Instance != null) { Instance = null; } GC.Collect(); } public static PluginLoader GetLoader() { if (Instance == null) { Instance = new PluginLoader(); } return Instance; } private IPluginContainer pluginContainer; public void LoadMenuAndPlugin(IPluginContainer container, Dispatcher dispatcher) { pluginContainer = container; if (Menus == null) { Plugins = new List(); Menus = LoadTreeMenu(dispatcher); sqliteHelper.Close(); dispatcher.Invoke(() => { LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.FINISHED }); }); } pluginContainer.DoCloseEvent += PluginContainer_DoCloseEvent; } private void PluginContainer_DoCloseEvent(object sender, EventArgs e) { Reset(); } private void LoadChildrenMenu() { foreach (var menu in Plugins) { CountdownEvent c = new CountdownEvent(1); Thread.Sleep(50); Application.Current.Dispatcher.Invoke(new Action(() => { try { LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.LOADING, Message = this.lang("App.IsLoadingMenu", menu.Name) } ); if (!string.IsNullOrEmpty(menu.DllPath)) { string dllPath = Path.Combine(PluginFolder, menu.DllPath); Assembly ass = Assembly.LoadFrom(dllPath); var tss = ass.GetTypes(); Type ClassType = ass.GetType(menu.ClassName); object Instance = Activator.CreateInstance(ClassType); menu.Content = Instance; if (Instance is IPlugin plugin) { } else { plugin = new PluginPackage(Instance); } plugin.SetLogger(LogManager.GetLogger(menu.Code)); string configFolder = Path.Combine(PathHelper.ConfigFolder, menu.Code); if (!Directory.Exists(configFolder)) { Directory.CreateDirectory(configFolder); } plugin.SetBaseFolder(configFolder); plugin.InitFinish(); pluginContainer.OnCloseEvent += plugin.OnClose; pluginContainer.DoCloseEvent += plugin.DoClose; Type SettingType = ass.GetType($"{menu.ClassName}_Setting"); if (SettingType != null) { object SettingInstance = Activator.CreateInstance(SettingType); if (SettingInstance is IFolderOwner fo) { fo.SetBaseFolder(configFolder); } menu.SettingControl = SettingInstance; } } LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.LOADING, Result = true, Message = this.lang("App.MenuLoadSuccess", menu.Name), }); } catch (Exception ex) { log.Error($"Load Plugin [{menu.Name}] Failed.", ex); LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.LOADING, Result = false, Message = this.lang("App.MenuLoadFailed", menu.Name, ex.Message, ex.StackTrace) }); } finally { c.Signal(); } })); c.Wait(); } } private PluginInfo ConvertPermission2PluginInfo(PermissionData data) { if (data.Type == "权限") return null; PluginInfo info = new PluginInfo { Code = data.Code, Name = data.Name, Type = data.Type, ParentCode = data.ParentCode, DllPath = data.DllPath, ClassName = data.ClassName, IconFont = data.IconFont //Icon = new BitmapImage(new Uri(Path.Combine(PathHelper.IconFolder, dr["iconPath"].ToString()))) }; if (data.Children != null && data.Children.Count > 0) { foreach (var child in data.Children) { var childInfo = ConvertPermission2PluginInfo(child); if (childInfo != null) info.Children.Add(childInfo); } } return info; } public List LoadTreeMenu(Dispatcher dispatcher) { List menus = new List(); Dictionary cache = new Dictionary(); try { List allPermissions = UserInfo.User?.AllPermissions; if (allPermissions != null) { Application.Current.Dispatcher.Invoke(() => { LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.INIT, NumData = allPermissions.Count, Message = this.lang("App.MenuCount", allPermissions.Count), }); foreach (PermissionData data in allPermissions) { if (data.Type == "Permission") continue; var menu = new PluginInfo { Code = data.Code, Name = data.Name, Type = data.Type, ParentCode = data.ParentCode, DllPath = data.DllPath, ClassName = data.ClassName, IconFont = data.IconFont }; cache[menu.Code] = menu; if (!cache.ContainsKey(menu.ParentCode)) { menus.Add(menu); } else { cache[menu.ParentCode].Children.Add(menu); } Plugins.Add(menu); } }); LoadChildrenMenu(); } } catch (Exception ex) { //LoadMessageAppend?.Invoke(this, ex.Message); } return menus; } } }