由于在实际的工作中, 碰见这样的一个问题:

一个软件, 销售给A客户 他需要所有功能,

但是销售给B客户, 他只需要其中的一部分,

1.如果我们在实际的开发过程中, 没有把一些功能模块区分开来的话, 那么带来的麻烦, 势必是要修改源代码。

2.直到有一天,B客户又说需要某些功能,这个时候, 我们又要修改一次源代码, 更新给客户 , 所以想了想, 如果每个功能块都独立开来, 动态去加载功能, 这样就不用改动源代码, 客户需要哪些功能, 注册那些DLL给他们使用。

?.实现思路
1.每个模块都用单独的程序集(DLL)分开  <反射动态加载>

2.需要指定每个功能模块的命名空间       <特性标记命名空间>

!.实现代码

1.程序中定义自定义特性, 用于映射程序的的模块信息和功能模块所在的命名空间

 /// <summary>
/// 模块编号.
/// </summary>
public enum ModuleID
{
None = ,
DataDictionary = ,
SystemManage =
} /// <summary>
/// 模块名称.
/// </summary>
public class ModuleNames
{
public const string DataDictionary = "基础数据";
public const string SystemManage = "系统管理";
} /// <summary>
/// 模块入口自定义特性
/// </summary>
public class AssemblyModuleEntry : Attribute
{ private ModuleID _moduleID;
private string _moduleName;
private string _moduleEntryNameSpace; /// <summary>
/// 模块编号
/// </summary>
public ModuleID ModuleID { get { return _moduleID; } } /// <summary>
/// 模块名称
/// </summary>
public string ModuleName { get { return _moduleName; } } /// <summary>
/// 模块名字空间
/// </summary>
public string ModuleEntryNameSpace { get { return _moduleEntryNameSpace; } } /// <summary>
/// 构造器
/// </summary>
/// <param name="moduleID">模块编号</param>
/// <param name="moduleName">模块名称</param>
/// <param name="moduleEntryNameSpace">模块名字空间</param>
public AssemblyModuleEntry(ModuleID moduleID, string moduleName, string moduleEntryNameSpace)
{
_moduleID = moduleID;
_moduleName = moduleName;
_moduleEntryNameSpace = moduleEntryNameSpace;
} }

在模块的程序集设置好新建的自定义特性 (如下):

// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyModuleEntry(ModuleID.DataDictionary, ModuleNames.DataDictionary, "My.DataDictionary.Form1")]

1.定义方法读取程序集(DLL)中的第一个特性信息

/// <summary>
/// 获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。
/// </summary>
public static AssemblyModuleEntry GetModuleEntry(Assembly asm)
{
AssemblyModuleEntry temp = new AssemblyModuleEntry(ModuleID.None, "", "");
if (asm == null) return temp; object[] list = asm.GetCustomAttributes(typeof(AssemblyModuleEntry), false);
if (list.Length > )
return (AssemblyModuleEntry)list[];
else
return temp;
}

2.保存AssemblyModuleEntry 的特性信息, 解析特性信息利用反射映射功能模块的主窗体

 /// <summary>
/// 加载模块主方法
/// </summary>
/// <param name="moduleinfo">模块信息</param>
/// <returns></returns>
public virtual bool LoadModule(ModuleInfo moduleinfo)
{
_ModuleFileName = moduleinfo.ModuleFile;
_ModuleAssembly = moduleinfo.ModuleAssembly;
string entry = GetModuleEntryNameSpace(_ModuleAssembly);
if (string.Empty == entry) return false; Form form = (Form)_ModuleAssembly.CreateInstance(entry); //根据命名空间加载Form
_ModuleMainForm = null; if (form is IModuleBase) _ModuleMainForm = (IModuleBase)form; return _ModuleMainForm != null;
}

3.将功能模块的功能都加载到全局缓存对象中, 创建首页的UI控件, 将缓存对象中的模块加载到首页中。

实际效果图:

注意: 反射是会带来性能的损耗, 但是经过合理的优化,还是对性能影响不大, 当个这个设计, 主要看每个人使用的取舍。

核心思想:

1.定义自定义特性

2.将功能命名空间存储到自定义特性中(主要用于反射获取到指定的功能界面区)

3.利用反射去获取目录下的有特性的程序集,加载指定的功能

4.将反射获取的指定界面转换成缓存对象

5.将缓存对象转换成首页指定的UI控件上。

PS: 关于权限的控制思路:

针对所登陆得用户, 获取当前用户所有的权限, 根据权限加载权限内的程序集。

---恢复内容结束---

最新文章

  1. CSS3魔法堂:CSS3滤镜及Canvas、SVG和IE滤镜替代方案详解
  2. Java基础01 ------ 从HelloWorld到面向对象
  3. UTC格式转换 &amp; 十六进制换算为十进制
  4. 2 通过JNI混合使用Java和C++ -----&gt; 访问数组
  5. jQuer中 height scrollTop
  6. 怎样检查手机是否root成功
  7. Cannot find a valid baseurl for repo: base
  8. 确定稳定的 Spring Cloud 相关环境版本
  9. 使用Jenkins pipeline流水线构建docker镜像和发布
  10. 通过WebClient模拟post上传文件到服务器
  11. 大数据入门到精通7--对复合value做reducebykey
  12. ARM架构处理器扩展结构-NEON
  13. BZOJ 4408: [Fjoi 2016]神秘数
  14. Centos安装自定义布局才能自己划分各个区的大小ctrl+z ,fg ,route -n ,cat !$ ,!cat ,XShell 设置, ifconfig CentOS远程连接 Linux中的输入流 第一节课
  15. PHP之array_flip()方法
  16. Dubbo基础配置
  17. PHP的普通传值与引用传值以及unset
  18. python抓取日本网站上iphone5的价格
  19. 椭圆参数方程中的θ(离心角Theta)
  20. Win 10 Enable .net framework 3.5 error (Error code:0x800F081F )

热门文章

  1. JSP编程技术5-购物车的实现-session会话对象
  2. vue11 vue实例方法
  3. Lambda表达式相当于一个函数
  4. idea+maven+springmvc
  5. apache-maven-3.0.4-bin.zip
  6. 学习NLP:《精通Python自然语言处理》中文PDF+英文PDF+代码
  7. 【HDU】5249-KPI(线段树+离散化)
  8. 怎样借助log4j把日志写入数据库中
  9. matlab中tic和toc使用方法
  10. modSecurity规则学习(二)——配置文件