Asp.Net 加载不同项目程序集
我们做项目时有时候不想添加别的项目的引用,但是那个项目又必须在 Global 中进行注册
最常见的就是插件机制,参考: https://shazwazza.com/post/Developing-a-plugin-framework-in-ASPNET-with-medium-trust.aspx
我们知道如果不添加引用在主程序中是无法使用其程序集的
我们可以自己加载其程序集
推荐做法是将dll文件先copy到 AppDomain.CurrentDomain.DynamicDirectory 中
然后在 AppDomain.CurrentDomain.DynamicDirectory 中进行 Assembly.Load
下面的代码没有进行copy了
1、命名空间顶部的程序开始时加载程序集必须添加,其中的2个参数分别时当前类及要执行的方法
2、使用Assembly.Load对程序集进行加载
[assembly: PreApplicationStartMethod(typeof(PatulouManager), "Initialize")] namespace IdeaSite.Web.Framework { public class PatulouManager { private const string PatulousPath = "~/Patulous"; public static void Initialize() { var patulouFolder = new DirectoryInfo(MapPath(PatulousPath)); var patulouFiles = patulouFolder.GetFiles("*.dll", SearchOption.AllDirectories); foreach (var patulouFile in patulouFiles.Where(x => !IsAlreadyLoaded(x))) { var shadowCopiedAssembly = Assembly.Load(AssemblyName.GetAssemblyName(patulouFile.FullName)); BuildManager.AddReferencedAssembly(shadowCopiedAssembly); } } /// <summary> /// 获取物理路径 /// </summary> /// <param name="path"></param> /// <returns></returns> public static string MapPath(string path) { if (HostingEnvironment.IsHosted) { //hosted return HostingEnvironment.MapPath(path); } //not hosted. For example, run in unit tests string baseDirectory = AppDomain.CurrentDomain.BaseDirectory; path = path.Replace("~/", "").TrimStart('/').Replace('/', '\\'); return Path.Combine(baseDirectory, path); } /// <summary> /// 是否已加入程序集 /// </summary> /// <param name="fileInfo"></param> /// <returns></returns> private static bool IsAlreadyLoaded(FileInfo fileInfo) { try { string fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileInfo.FullName); if (fileNameWithoutExt == null) throw new Exception(string.Format("Cannot get file extension for {0}", fileInfo.Name)); foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) { string assemblyName = a.FullName.Split(new[] { ',' }).FirstOrDefault(); if (fileNameWithoutExt.Equals(assemblyName, StringComparison.InvariantCultureIgnoreCase)) return true; } } catch (Exception exc) { Debug.WriteLine("Cannot validate whether an assembly is already loaded. " + exc); } return false; } } }