///*************************************************************************/ ///* ///* 文件名 :ModuleLoader.cs ///* 程序说明 : 模块加载器 ///* 原创作者 :孙中吕 ///* ///* Copyright 2006-2021 C/S框架网 www.csframework.com ///* ///**************************************************************************/ using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Reflection; using System.Windows.Forms; namespace CSFrameworkV5.Core { #region 模块加载器 /// /// 模块加载器基类 /// public class ModuleLoaderBase { /// /// 模块文件名(DLL文件) /// protected string _ModuleFileName; /// /// 如果加载了模块,返回该模块的主窗体对象. /// protected IModuleBase _ModuleMainForm; /// /// 模块所在的程序集 /// protected Assembly _ModuleAssembly; /// /// 模块所在的程序集 /// public Assembly ModuleAssembly => _ModuleAssembly; /// /// 返回当前模块的名称,从AssemblyModuleEntry自定义特性内获取信息。 /// public string GetCurrentModuleName(Assembly asm) { return GetModuleEntry(asm).ModuleName; } /// /// 模块主窗体 /// public IModuleBase ModuleMainForm => _ModuleMainForm; /// /// 加载模块的菜单(支持一个模块内有多个顶级菜单) /// /// 程序主窗体的菜单 public virtual void LoadMenu(MenuStrip moduleMenus) { var moduleMenu = _ModuleMainForm.GetModuleMenu(); //当前模块的菜单 if (moduleMenu == null || moduleMenu.Items.Count == 0) return; if (_ModuleMainForm != null) while (moduleMenu.Items.Count > 0) //加载所有顶级菜单 { var startIndex = moduleMenus.Items.Count == 0 ? 0 : moduleMenus.Items.Count; moduleMenus.Items.Insert(startIndex, moduleMenu.Items[0]); } } /// /// 加载模块主窗体 /// /// 模块信息 /// public virtual bool LoadModule(ModuleInfo moduleinfo) { _ModuleMainForm = null; _ModuleFileName = moduleinfo.ModuleFile; _ModuleAssembly = moduleinfo.ModuleAssembly; //获取模块主窗体的命名空间 var entry = GetModuleEntryNameSpace(_ModuleAssembly); if (string.Empty == entry) return false; var form = (Form)_ModuleAssembly.CreateInstance(entry); if (form is IModuleBase) _ModuleMainForm = (IModuleBase)form; return _ModuleMainForm != null; } /// /// 枚举主程序所在目录下所有DLL文件,获取业务模块列表并转换为ModuleInfo集合. /// /// 查找的文件扩展名 /// public virtual IList GetModuleList(string searchPattern) { IList list = new List(); try { var files = new string[] { }; //模块文件(*.dll) var root = Application.StartupPath; if (Directory.Exists(root)) files = Directory.GetFiles(root, searchPattern); //for test //File.WriteAllText(@"c:\cstest.txt", root + " " + searchPattern); //枚举所有文件 foreach (var mod in files) { Assembly asm = null; try { //加载.Net Framework DLL文件 asm = Assembly.LoadFile(mod); } catch { continue; } var id = GetModuleID(asm); var name = GetCurrentModuleName(asm); if (id != 0) { var m = new ModuleInfo(asm, id, name, mod); list.Add(m); } } SortModule(list); //模块排序. return list; } catch (Exception ex) { return list; } } /// /// 模块排序 /// /// public virtual void SortModule(IList list) { int i = 0, j = 1; ModuleInfo temp; var done = false; while (j < list.Count && !done) { done = true; for (i = 0; i < list.Count - j; i++) if ((list[i] as ModuleInfo).ModuleID > (list[i + 1] as ModuleInfo).ModuleID) { done = false; temp = list[i]; list[i] = list[i + 1]; list[i + 1] = temp; } } } /// /// 将数据库获取的模块列表转换为ModuleInfo集合. /// /// 数据库获取的模块列表 /// public virtual IList GetModuleList(DataTable fileList) { IList moduleList = new List(); try { var file = ""; //模块文件(*.dll) var rs = fileList.Select(" IsVisible='Y' ", " SortID ASC"); //模块可用和排序 foreach (var R in rs) { //检查文件是否存在 file = Application.StartupPath + "\\" + R["FileName"].ToStringEx(); if (!File.Exists(file)) continue; Assembly asm = null; try { asm = Assembly.LoadFile(file); } catch { continue; } var id = GetModuleID(asm); var name = GetCurrentModuleName(asm); if (id != 0) { var m = new ModuleInfo(asm, id, name, file); moduleList.Add(m); } } return moduleList; } catch (Exception ex) { return moduleList; } } /// /// 获取程序集的自定义特性。 /// /// public AssemblyModuleEntry GetModuleEntry() { return GetModuleEntry(_ModuleAssembly); } /// /// 通过检查Assembly定义的特性AssemblyModuleEntry,判断加载的文件是否业务模块文件。 /// 程序目录有不同类别的DLL文件,若没有定义AssemblyModuleEntry特性即不是业务模块。 /// public bool IsModuleFile(string moduleFile) { try { var asm = Assembly.LoadFile(moduleFile); return GetModuleID(asm) != 0; } catch { return false; } } /// /// 每个业务模块的主窗体定义一个TabPage与Panel, 将模块主窗体的Panel组件嵌套在主窗体的TabPage内。 /// public virtual void LoadGUI(object mainTabControl) { } #region 类公共静态方法 /// /// 查找子菜单,深度搜索 /// public static ToolStripMenuItem GetMenuItem(ToolStrip mainMenu, string menuName) { var items = mainMenu.Items.Find(menuName, true); if (items.Length > 0 && items[0] is ToolStripMenuItem) return (ToolStripMenuItem)items[0]; else return null; } /// /// 获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。 /// public static AssemblyModuleEntry GetModuleEntry(Assembly asm) { var temp = new AssemblyModuleEntry(0, "", ""); if (asm == null) return temp; var list = asm.GetCustomAttributes(typeof(AssemblyModuleEntry), false); if (list.Length > 0) return (AssemblyModuleEntry)list[0]; else return temp; } /// /// 获取模块主窗体名字空间 /// public static string GetModuleEntryNameSpace(Assembly asm) { return GetModuleEntry(asm).ModuleEntryNameSpace; } /// /// 获取模块编号 /// public static int GetModuleID(Assembly asm) { return GetModuleEntry(asm).ModuleID; } #endregion /// /// 判断当前用户是否有该模块的权限 /// /// 用户权限数据 /// public bool CanAccessModule(DataTable userRights) { //管理员例外 if (Loginer.CurrentUser.IsAdmin()) return true; var mainMenu = _ModuleMainForm.GetModuleMenu(); var rows = userRights.Select(string.Format("MenuName='{0}'", mainMenu.Items[0].Name)); return rows != null && rows.Length > 0; } /// /// 程序集对象引用置空,优化GC回收内存 /// public void ClearAssemble() { _ModuleAssembly = null; _ModuleMainForm = null; } } #endregion }