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;
        }
    }
}
原文地址:https://www.cnblogs.com/ideacore/p/7814925.html