思路:动态加载模块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