以下是项目中的一个类,用于加载模块DLL及,此类演示了如何在运行文件夹下搜索DLL并通过Assembly类进行加载。
using Core.Dependency; using Core.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Web; using System.Web.Compilation; using System.Web.Hosting; [assembly: PreApplicationStartMethod(typeof(Core.Modules.ModuleManager), "Initialize")] namespace Core.Modules { public class ModuleManager { static ModuleManager() { string moduleStartPath = HostingEnvironment.MapPath("~/Modules"); if (moduleStartPath == null) throw new DirectoryNotFoundException("Modules"); ModuleStartFolder = new DirectoryInfo(moduleStartPath); string webBinPath = HostingEnvironment.MapPath("~/bin"); if (string.IsNullOrEmpty(webBinPath)) throw new DirectoryNotFoundException("bin"); WebBinPath = webBinPath; } /// <summary> /// The Module Definition Start folder /// </summary> private static readonly DirectoryInfo ModuleStartFolder; private static readonly string WebBinPath; public static readonly Dictionary<string, IModuleDefinition> ModuleDefinitions = new Dictionary<string,IModuleDefinition>(); /// <summary> /// Initialize method that registers all plugins /// </summary> public static void Initialize() { Array.ForEach(ModuleStartFolder.GetDirectories(), n => { CopyAssembly(n); }); InitializeModule(new DirectoryInfo(WebBinPath)); } private static void CopyAssembly(DirectoryInfo directory) { var dirs = directory.GetDirectories("bin", SearchOption.TopDirectoryOnly); if (dirs == null || dirs.Length == 0) return; var binFolder = dirs.FirstOrDefault(); try { var assemblies = binFolder.GetFiles("*.dll", SearchOption.AllDirectories); Array.ForEach(assemblies, n => { n.CopyTo(WebBinPath + "\\" + n.Name, true); }); } catch (Exception ex) { var logger = new Logger(); logger.LogError(ex.Message, ex); } } private static void InitializeModule(DirectoryInfo directory) { try { //AppDomain.CurrentDomain.AppendPrivatePath(directory.FullName); var assemblies = directory.GetFiles("*.dll", SearchOption.AllDirectories) .Select(x => AssemblyName.GetAssemblyName(x.FullName)) .Select(x => Assembly.Load(x.FullName)); //var assemblies = binFolder.GetFiles(string.Format("{0}.dll", directory.Name), SearchOption.TopDirectoryOnly) // .Select(x => AssemblyName.GetAssemblyName(x.FullName)) // .Select(x => Assembly.Load(x.FullName)); foreach (var assembly in assemblies) { //Add the plugin as a reference to the application BuildManager.AddReferencedAssembly(assembly); Type type = assembly.GetTypes().Where(t => t.GetInterface(typeof(IModuleDefinition).Name) != null).FirstOrDefault(); if (type != null && !type.IsAbstract && !type.IsInterface) { var module = (IModuleDefinition)Activator.CreateInstance(type); if (!ModuleDefinitions.ContainsKey(module.ModuleFolder)) { ModuleDefinitions.Add(module.ModuleFolder, module); } } } } catch (Exception ex) { var logger = new Logger(); logger.LogError(ex.Message,ex); } } } }
关注点:
1. 以下特性标识 在APP的开始执行任何方法之前执行ModuleManager中的方法Initialize.
[assembly: PreApplicationStartMethod(typeof(Core.Modules.ModuleManager), "Initialize")]
2. 找到web站点目录。关键是类HostingEnvironment里有关于运行环境的一些处理方法。详细参见:http://msdn.microsoft.com/zh-cn/library/1677yx1a%28VS.80%29.aspx
string moduleStartPath = HostingEnvironment.MapPath("~/Modules");
3. AppDomain类的应用,参见:http://www.cnblogs.com/foman/archive/2009/10/18/1585655.html
AppDomain.CurrentDomain.AppendPrivatePath(directory.FullName);
4. DirectoryInfo, FileInfo, File类的应用,主要用于查找文件,Copy文件。
5. AssemblyName,Assembly加载DLL.
6. BuildManager类的应用,主要用于管理Asp.net的编译
7. Activator类用于创建对象。