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<PluginInfo> Menus { get; private set; }
|
public List<PluginInfo> Plugins { get; private set; }
|
public static PluginLoader Instance { get; private set; }
|
|
public event EventHandler<LoadMsg> 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<PluginInfo>();
|
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<PluginInfo> LoadTreeMenu(Dispatcher dispatcher)
|
{
|
List<PluginInfo> menus = new List<PluginInfo>();
|
Dictionary<string, PluginInfo> cache = new Dictionary<string, PluginInfo>();
|
try
|
{
|
List<PermissionData> 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;
|
}
|
}
|
}
|