思路:动态加载模块DLL
过程:
1、定义模块接口
2、实现模块接口
3、配置文件配置模块路径
4、产品App加载模块
模块接口
public interface IModules
{ IEnumerable<IModule> GetModules(); }
模块实现接口
public class Modules : IModules { public IEnumerable<IModule> GetModules() { List<IBxModule> modules = new List<IModule>(); modules.Add(new MyModule()); return modules; } }
定义组件特性
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] public class ModulesAttribute : Attribute { public ModulesAttribute(Type type); public IModules GetModules(); }
注册组件程序集
[assembly: ModulesAttribute(typeof(Modules))]
注册配置文件(用于检查模块是否注册)
<Module id="MyModule" name="我的模块" relativePath="MyModule" dll="MyModule.dll" />
产品App加载模块
全局配置信息
/// <summary> 系统配置文件接口 </summary> public interface ISystemPath { string HeBianGuDocuments { get; } /// <summary> bin所在目录 </summary> string BinPath { get; } /// <summary> 配置文件所在目录 </summary> string ConfigPath { get; } string GlobalConfigPath { get; } string CultureConfigPath { get; } string ProjectsPath { get; } /// <summary> 模块注册文件所在目录 </summary> string RegistriesConfigPath { get; set; } string ModulesDllPath { get; set; } string ApplicationsConfigPath { get; set; } }
初始化模块产品配置路径(主要包括:bin目录,Confige目录,日志)
/// <summary> 加载配置文件 </summary> void InitResource() { string exeFileFullPath = Assembly.GetEntryAssembly().Location; string exeName = Path.GetFileNameWithoutExtension(exeFileFullPath); string binPath = Path.GetDirectoryName(exeFileFullPath); // 初始化系统文件 HeSystemInfo.Instance.Init(binPath); string configFilePath = Path.Combine(HeSystemInfo.Instance.SystemPath.CultureConfigPath, "Applications", "TestApp", "StringResource.xml"); // 初始化资源文件 StringResource.Init(configFilePath); string logFilePath = Path.GetDirectoryName(binPath); // 初始化日志 Output.InitLogger(logFilePath, System.Diagnostics.Process.GetCurrentProcess().ProcessName); // 初始化缓存 _moduleInstances = new ModuleInstanceCenter(this); }
加载配置文件模块信息
/// <summary> 加载模块 </summary> void InitConfigerModules() { // 加载配置文件 string binPath = AppDomain.CurrentDomain.BaseDirectory; // 初始化配置文件 string exeFileFullPath = Assembly.GetEntryAssembly().Location; string exeName = Path.GetFileNameWithoutExtension(exeFileFullPath); _applicationInfo = new ApplicationInfo(exeName); // 初始化图标 string appConfigPath = System.IO.Path.Combine(HeSystemInfo.Instance.SystemPath.CultureConfigPath, "Applications", exeName); if (File.Exists(System.IO.Path.Combine(appConfigPath + @"\" + exeName + @".ico"))) this.Icon = new Icon(System.IO.Path.Combine(appConfigPath + @"\" + exeName + @".ico")); else this.Icon = Resources.defalt; // 初始化模块 List<string> ids = new List<string>(); foreach (IHeFunctionModule module in _applicationInfo.Modules) { if (ids.IndexOf(module.ID) < 0) ids.Add(module.ID); } InitMenu(); //this.proInfo.labelControl8.Text = string.Format("<size=14>[{0}{1}]</size>", appName, AppLogic.Instance.Rs.TextByID(StringID.ProjectInfo)); // 初始化窗口名 //SetFormTitle(); // 初始化输出日志 //InitGrid(); }
加载注册模块方法
class ApplicationInfo : IHeApplicationInfo {
List<IHeFunctionModule> _modules = new List<IHeFunctionModule>(); public List<IHeFunctionModule> Modules { get { return _modules; } } public ApplicationInfo(string appID) { _id = appID; InitApplicationConfig(); } public void InitApplicationConfig() { string appConfigPath = HeSystemInfo.Instance.Regisries.GetApplicationConfigPath(_id); _configPath = appConfigPath; string configFilePath = Path.Combine(appConfigPath, "Config.xml"); XmlDocument doc = new XmlDocument(); doc.Load(configFilePath); XmlElement applicationInfoNode = doc.DocumentElement.SelectSingleNode("ApplicationInfo") as XmlElement; _modules.Clear();
XmlElement modulesNode = doc.DocumentElement.SelectSingleNode("Modules") as XmlElement; XmlNodeList nodes = modulesNode.ChildNodes; IHeFunctionModule module = null; foreach (XmlElement one in nodes) { string viStr = one.GetAttribute("visible"); bool visible = true; if (!string.IsNullOrWhiteSpace(viStr)) visible = bool.Parse(viStr); if (!visible) continue; string moduleID = one.GetAttribute("id"); int i = 0; bool find = false; if (!find) { if (moduleID.ToUpper() == "EXE" || moduleID.ToUpper() == "URL") { //module = new ThirdModule(moduleID, one.GetAttribute("path"), one.GetAttribute("arg")); } else { module = HeModulesManager.Instance.GetFunctionModule(moduleID); } if (module == null) continue; _modules.Add(module); i = _modules.Count - 1; } } }
public class HeModulesManager { public IHeFunctionModule GetFunctionModule(string id) { HeModulePath modulePath = HeSystemInfo.Instance.Regisries.GetModulePath(id); if (modulePath == null) return null; try { Assembly ass = Assembly.LoadFile(modulePath.DllFilePath); object[] objs = ass.GetCustomAttributes(typeof(HeModulesAttribute), false); IHeModules modules = (objs[0] as HeModulesAttribute).GetModules(); return modules.GetModule(id, HeModuleType.FuncionModule) as IHeFunctionModule; } catch (System.Exception e) { return null; } } static HeModulesManager s_instance = new HeModulesManager(); public static HeModulesManager Instance { get { return s_instance; } } } }
源代码: https://github.com/HeBianGu/ProductWork.git