啊鑫
2024-07-09 0552fcc8cb73fc3021e2915129f55a42ed3f20e5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
///*************************************************************************/
///*
///* 文件名    :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 模块加载器
 
    /// <summary>
    /// 模块加载器基类
    /// </summary>
    public class ModuleLoaderBase
    {
        /// <summary>
        /// 模块文件名(DLL文件)
        /// </summary>
        protected string _ModuleFileName;
 
        /// <summary>
        /// 如果加载了模块,返回该模块的主窗体对象.
        /// </summary>
        protected IModuleBase _ModuleMainForm;
 
        /// <summary>
        /// 模块所在的程序集
        /// </summary>
        protected Assembly _ModuleAssembly;
 
        /// <summary>
        /// 模块所在的程序集
        /// </summary>
        public Assembly ModuleAssembly => _ModuleAssembly;
 
        /// <summary>
        /// 返回当前模块的名称,从AssemblyModuleEntry自定义特性内获取信息。
        /// </summary>
        public string GetCurrentModuleName(Assembly asm)
        {
            return GetModuleEntry(asm).ModuleName;
        }
 
        /// <summary>
        /// 模块主窗体
        /// </summary>
        public IModuleBase ModuleMainForm => _ModuleMainForm;
 
        /// <summary>
        /// 加载模块的菜单(支持一个模块内有多个顶级菜单)
        /// </summary>
        /// <param name="menuStrip">程序主窗体的菜单</param>
        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]);
                }
        }
 
        /// <summary>
        /// 加载模块主窗体
        /// </summary>
        /// <param name="moduleinfo">模块信息</param>
        /// <returns></returns>
        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;
        }
 
        /// <summary>
        /// 枚举主程序所在目录下所有DLL文件,获取业务模块列表并转换为ModuleInfo集合.
        /// </summary>
        /// <param name="searchPattern">查找的文件扩展名</param>
        /// <returns></returns>
        public virtual IList<ModuleInfo> GetModuleList(string searchPattern)
        {
            IList<ModuleInfo> list = new List<ModuleInfo>();
 
            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;
            }
        }
 
        /// <summary>
        /// 模块排序
        /// </summary>
        /// <param name="list"></param>
        public virtual void SortModule(IList<ModuleInfo> 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;
                    }
            }
        }
 
        /// <summary>
        /// 将数据库获取的模块列表转换为ModuleInfo集合.
        /// </summary>
        /// <param name="fileList">数据库获取的模块列表</param>
        /// <returns></returns>
        public virtual IList<ModuleInfo> GetModuleList(DataTable fileList)
        {
            IList<ModuleInfo> moduleList = new List<ModuleInfo>();
            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;
            }
        }
 
        /// <summary>
        /// 获取程序集的自定义特性。
        /// </summary>
        /// <returns></returns>
        public AssemblyModuleEntry GetModuleEntry()
        {
            return GetModuleEntry(_ModuleAssembly);
        }
 
        /// <summary>
        /// 通过检查Assembly定义的特性AssemblyModuleEntry,判断加载的文件是否业务模块文件。
        /// 程序目录有不同类别的DLL文件,若没有定义AssemblyModuleEntry特性即不是业务模块。
        /// </summary>
        public bool IsModuleFile(string moduleFile)
        {
            try
            {
                var asm = Assembly.LoadFile(moduleFile);
                return GetModuleID(asm) != 0;
            }
            catch
            {
                return false;
            }
        }
 
        /// <summary>
        /// 每个业务模块的主窗体定义一个TabPage与Panel, 将模块主窗体的Panel组件嵌套在主窗体的TabPage内。        
        /// </summary>
        public virtual void LoadGUI(object mainTabControl)
        {
        }
 
        #region 类公共静态方法
 
        /// <summary>
        /// 查找子菜单,深度搜索
        /// </summary>
        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;
        }
 
        /// <summary>
        /// 获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。
        /// </summary>
        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;
        }
 
        /// <summary>
        /// 获取模块主窗体名字空间
        /// </summary>
        public static string GetModuleEntryNameSpace(Assembly asm)
        {
            return GetModuleEntry(asm).ModuleEntryNameSpace;
        }
 
        /// <summary>
        /// 获取模块编号
        /// </summary>
        public static int GetModuleID(Assembly asm)
        {
            return GetModuleEntry(asm).ModuleID;
        }
 
        #endregion
 
        /// <summary>
        /// 判断当前用户是否有该模块的权限
        /// </summary>
        /// <param name="userRights">用户权限数据</param>
        /// <returns></returns>
        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;
        }
 
        /// <summary>
        /// 程序集对象引用置空,优化GC回收内存
        /// </summary>
        public void ClearAssemble()
        {
            _ModuleAssembly = null;
            _ModuleMainForm = null;
        }
    }
 
    #endregion
}