| | |
| | | using System; |
| | | using HMI.Core.Api; |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Util; |
| | | using log4net; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.Data; |
| | | using System.IO; |
| | | using System.Reflection; |
| | | using System.Windows.Media.Imaging; |
| | | using HMI.Core.Api; |
| | | using HMI.Core.Util; |
| | | using log4net; |
| | | 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 ObservableCollection<PluginInfo> Menus { get; private set; } |
| | | public ObservableCollection<PluginInfo> Plugins { get; private set; } |
| | | |
| | | public List<PluginInfo> Menus { get; private set; } |
| | | public List<PluginInfo> Plugins { get; private set; } |
| | | public static PluginLoader Instance { get; private set; } |
| | | |
| | | public event EventHandler<string> LoadMessageAppend; |
| | | public event EventHandler<LoadMsg> LoadMessageAppend; |
| | | |
| | | private PluginLoader() |
| | | { |
| | | sqliteHelper = new SqliteHelper(PathHelper.DatabasePath); |
| | | } |
| | | |
| | | public static void Reset() |
| | | { |
| | | if (Instance != null) |
| | | { |
| | | Instance = null; |
| | | } |
| | | } |
| | | |
| | | public static PluginLoader GetLoader() |
| | |
| | | return Instance; |
| | | } |
| | | |
| | | public void LoadMenuAndPlugin() |
| | | private IPluginContainer pluginContainer; |
| | | public void LoadMenuAndPlugin(IPluginContainer container, Dispatcher dispatcher) |
| | | { |
| | | pluginContainer = container; |
| | | if (Menus == null) |
| | | { |
| | | Plugins = new ObservableCollection<PluginInfo>(); |
| | | Menus = LoadTreeMenu(); |
| | | } |
| | | } |
| | | |
| | | private void LoadChildrenMenu(PluginInfo menu) |
| | | { |
| | | LoadMessageAppend?.Invoke(this, $"正在加载{menu.Name}菜单..."); |
| | | try |
| | | { |
| | | if (!string.IsNullOrEmpty(menu.DllPath)) |
| | | Plugins = new List<PluginInfo>(); |
| | | Menus = LoadTreeMenu(dispatcher); |
| | | sqliteHelper.Close(); |
| | | dispatcher.Invoke(() => |
| | | { |
| | | string dllPath = Path.Combine(PluginFolder, menu.DllPath); |
| | | Assembly ass = Assembly.LoadFrom(dllPath); |
| | | Type ClassType = ass.GetType(menu.ClassName); |
| | | object Instance = Activator.CreateInstance(ClassType); |
| | | menu.Content = Instance; |
| | | if (Instance is IPlugin plugin) |
| | | { |
| | | 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(); |
| | | } |
| | | Type SettingType = ass.GetType($"{menu.ClassName}_Setting"); |
| | | if (SettingType != null) |
| | | { |
| | | object SettingInstance = Activator.CreateInstance(SettingType); |
| | | menu.SettingControl = SettingInstance; |
| | | } |
| | | } |
| | | LoadMessageAppend?.Invoke(this, new LoadMsg { Type = LoadMsgType.FINISHED }); |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | } |
| | | private void LoadChildrenMenu() |
| | | { |
| | | foreach (var menu in Plugins) |
| | | { |
| | | LoadMessageAppend?.Invoke(this, $"{ex.Message} {ex.StackTrace}"); |
| | | 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); |
| | | Type ClassType = ass.GetType(menu.ClassName); |
| | | object Instance = Activator.CreateInstance(ClassType); |
| | | menu.Content = Instance; |
| | | if (Instance is IPlugin plugin) |
| | | { |
| | | 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 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 ObservableCollection<PluginInfo> LoadTreeMenu() |
| | | public List<PluginInfo> LoadTreeMenu(Dispatcher dispatcher) |
| | | { |
| | | ObservableCollection<PluginInfo> data = new ObservableCollection<PluginInfo>(); |
| | | //LoadMessageAppend?.Invoke(this, "开始加载菜单..."); |
| | | List<PluginInfo> data = new List<PluginInfo>(); |
| | | Dictionary<string, PluginInfo> cache = new Dictionary<string, PluginInfo>(); |
| | | try |
| | | { |
| | | LoadMessageAppend?.Invoke(this, "开始加载菜单..."); |
| | | DataTable dt = sqliteHelper.GetDataTable(@"SELECT * FROM menu ORDER BY level,id;"); |
| | | 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.id;"; |
| | | |
| | | DataTable dt = sqliteHelper.GetDataTable(sql); |
| | | if (dt != null) |
| | | { |
| | | LoadMessageAppend?.Invoke(this, $"共有{dt.Rows.Count}条菜单待加载..."); |
| | | foreach (DataRow dr in dt.Rows) |
| | | Application.Current.Dispatcher.Invoke(() => |
| | | { |
| | | string path = Path.Combine(PathHelper.IconFolder, dr["iconPath"].ToString()); |
| | | var menu = new PluginInfo |
| | | 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) |
| | | { |
| | | Code = dr["code"].ToString(), |
| | | Name = dr["name"].ToString(), |
| | | ParentCode = dr["parentCode"].ToString(), |
| | | DllPath = dr["dllPath"].ToString(), |
| | | ClassName = dr["className"].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); |
| | | string path = Path.Combine(PathHelper.IconFolder, dr["iconPath"].ToString()); |
| | | var menu = new PluginInfo |
| | | { |
| | | Code = dr["code"].ToString(), |
| | | Name = dr["name"].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); |
| | | } |
| | | else |
| | | { |
| | | cache[menu.ParentCode].Children.Add(menu); |
| | | } |
| | | Plugins.Add(menu); |
| | | LoadChildrenMenu(menu); |
| | | } |
| | | }); |
| | | LoadChildrenMenu(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LoadMessageAppend?.Invoke(this, ex.Message); |
| | | //LoadMessageAppend?.Invoke(this, ex.Message); |
| | | } |
| | | return data; |
| | | } |