using HMI.Core.Api; using HMI.Core.Entity; using HMI.Core.Util; using log4net; using System; using System.Collections.Generic; using System.Data; 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 bool Completed { get; private set; } = false; 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; } } 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 }); }); } } private void LoadChildrenMenu() { foreach (var menu in Plugins) { CountdownEvent c = new CountdownEvent(1); Thread.Sleep(80); 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(); } } public List LoadTreeMenu(Dispatcher dispatcher) { //LoadMessageAppend?.Invoke(this, "开始加载菜单..."); List data = new List(); Dictionary cache = new Dictionary(); try { UserInfo user = UserInfo.User; string sql = $@"SELECT m.* FROM menu AS m INNER JOIN role_menu_rel AS rrel ON m.code = rrel.menuCode INNER JOIN role AS r ON rrel.roleCode = r.code INNER JOIN user_role_rel AS urel ON r.code = urel.roleCode AND urel.username = '{user.Username}' ORDER BY m.level,m.sort, m.id;"; DataTable dt = sqliteHelper.GetDataTable(sql); if (dt != null) { Application.Current.Dispatcher.Invoke(() => { LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.INIT, NumData = dt.Rows.Count, Message = this.lang("App.MenuCount", dt.Rows.Count), }); foreach (DataRow dr in dt.Rows) { string path = Path.Combine(PathHelper.IconFolder, dr["iconPath"].ToString()); var menu = new PluginInfo { Code = dr["code"].ToString(), Name = dr["name"].ToString(), Type = dr["type"].ToString(), ParentCode = dr["parentCode"].ToString(), DllPath = dr["dllPath"].ToString(), ClassName = dr["className"].ToString(), IconFont = dr["icon"].ToString() //Icon = new BitmapImage(new Uri(Path.Combine(PathHelper.IconFolder, dr["iconPath"].ToString()))) }; cache[menu.Code] = menu; if (!cache.ContainsKey(menu.ParentCode)) { data.Add(menu); } else { cache[menu.ParentCode].Children.Add(menu); } Plugins.Add(menu); } }); LoadChildrenMenu(); } } catch (Exception ex) { //LoadMessageAppend?.Invoke(this, ex.Message); } return data; } } }