在开发过程中各个,各个模块需要分开来开发,开发完成后最后合并将这些模块的信息存入到数据库中。在这个时候就需要在程序开始的时候需要加载这些模块信息。具体的实现方法就是通过过反射的方式获取这些模块的信息。
准备工作:
1.我在这个项目中做了一个接口IAppPlugIn
string PlugInId { get; }
string PlugInName { get; }
string RouteName { get; }
string GetUrl(string routes,string controller)//这个方法暂时不用
2.在项目中添加Areas的一个文件夹用来村放各个模块
例如:文件管理模块 会有一个FileManageAreaRegistration.cs的文件
在这个文件里面继承IAppPlugIn 并完善模块信息
这些模块都是一些实现功能的父节点,下面还有一些子功能
3.模块的子功能
3-1.首先新建一个特性 里面主要用来标识子功能
ParentModuleId就是上面的那个模块的PlugInId
下面的属性就是存储子功能的信息
3-2:子功能的实现 就是一个控制器
存入相应的信息 。首先说明一些这里的控制器全部继承自一个叫HandlerLoginInfoController的控制器,他是这些控制器的BaseController,然后有这个控制器再继承Controller,因为每个控制器都有Index detail等方法所以就将其封装起来。
准备工作到此结束。
使用反射来加载这些模块
在全局文件中的Application_Start()方法中实现:
首先使用常规的反射:
// //Dll文件所在的文件夹
// string dllFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin");
// //加载文件路径下的dll文件
// string[] dllFiles = Directory.GetFiles(dllFilePath, "*.dll");
// //找到Z2开头的dll文件
// foreach (string item in dllFiles)
// {
// //获取到Z2.Web
// if (Path.GetFileName(item).StartsWith("Z2"))
// {
// //加载程序集
// Assembly ass = Assembly.LoadFile(item);
// //获取所有的类
// Type[] types = ass.GetExportedTypes();
// foreach (Type tt in types)
// {
// //找到所有继承字AreaRegistration的子类
// if (tt.IsSubclassOf(typeof(AreaRegistration)) && !tt.IsAbstract)
// {
// //初始化对象
// object obj = Activator.CreateInstance(tt);
// //根节点的文件夹(Area)名称
// string rootAreaName = tt.GetProperty("AreaName").GetValue(obj, null).ToString();
// //根节点Id
// string rootId = tt.GetProperty("PlugInId").GetValue(obj, null).ToString();
// //根节点的名称
// string rootName = tt.GetProperty("PlugInName").GetValue(obj, null).ToString();
// //根节点添加到数据库中
// Operate(rootId, "0", rootName);
// //功能模块类所在的命名空间
// string namesp = tt.Namespace + ".Controllers";
// //加载某个节点下的模块
// Assembly allClass = Assembly.GetExecutingAssembly();
// //遍历每个类型
// foreach (Type cla in allClass.GetTypes())
// {
// if (cla.Namespace == namesp)
// {
// string mid = string.Empty;
// string mName = string.Empty;
// //找具有相应特性标签的类 获取相应的特性值
// ModuleActionAttribute moduleAttr = cla.GetCustomAttribute(typeof(ModuleActionAttribute)) as ModuleActionAttribute;
// if (moduleAttr != null)
// {
// mid = moduleAttr.ModuleId;
// mName = moduleAttr.ModuleName;
// //将注册的模块添加到数据库中
// //1.先判断是否已经存在在数据库中
// Operate(mid, rootId, mName);
// }//end if
// else
// continue;
// }//end if
// }//end foreach
// }//end if
// }//end foreach
// }//end if
// }//end foreach
这种方法太过繁杂,不建议,效率差。
使用Linq的方式:
//所有实现IAppPlugIn的所有类
var allCompleteCla = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IAppPlugin))))
.ToArray();
//遍历所有的实现类
foreach (var item in allCompleteCla)
{
var obj = Activator.CreateInstance(item) as IAppPlugin;
if (obj == null) continue;
var rootId = obj.PlugInId;//模块Id
var rootName = obj.PlugInName;//模块名称
var routeName = obj.RouteName; //路由名
string namesp = item.Namespace + ".Controllers";
Operate(rootId, "0", rootName, "");
//加载所有继承自HandlerLoginInfoController的Controllers
var allControllers = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t => t.IsSubclassOf(typeof(Controller))))
.ToArray();
//遍历每个控制器类
foreach (var cla in allControllers)
{
if (cla.Namespace != namesp) continue;
var moduleAttr = cla.GetCustomAttribute(typeof(ModuleActionAttribute)) as ModuleActionAttribute;
if (moduleAttr != null)
{
var mId = moduleAttr.ModuleId;
var mName = moduleAttr.ModuleName;
//拼接链接路径
var controller = cla.Name.Substring(0, cla.Name.Length - 10);//只获取Controller前面的部分
var url = RouteTable.Routes[routeName] as Route;
var urlAddress = obj.GetUrl(url.Url.Split('/')[0], controller);
//将注册的模块添加到数据库中
Operate(mId, rootId, mName, urlAddress);
}//end if
else
continue;
}//end foreach
}//end foreach
方法还有待优化。
**
**