C#加载程序集失败后从指定路径重新加载程序集

项目场景:

    当我们在进行插件开发的时候经常会遇到一个问题:当前程序运行路径和程序集加载路径不一样,最简单的方法是,将当前程序需要的dll放到我们使用的软件的程序的根目录下。

但是我们能不能从代码上解决这个问题,当它加载失败的时候使它从另一个地方重新加载dll呢。


问题描述

加载失败的时候从另一个地方重新加载dll ,废话不多说,直接上代码(可以直接用):

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace ZONZCENAddin
{
    /// <summary>
    /// 用于确定解决方案文件(在文件系统上)的路径并加载程序集
    /// </summary>
    public class AssemblyLoader : IDisposable
    {
        /// <summary>
        /// 返回fileInfo中的文件列表
        /// </summary>
        public static IEnumerable<string> GetFiles(DirectoryInfo fileInfo)
        {
            return from file in fileInfo.EnumerateFiles()
                   where (file.Name.EndsWith(".dll") || file.Name.EndsWith(".exe") || file.Name.EndsWith(".xaml") || file.Name.EndsWith(".cs"))
                   select file.FullName;
        }
        private static string _executingPath;
        public AssemblyName _assemblyName;

        private DirectoryInfo _fileInfo;
        private IEnumerable<string> _assemblies;

        readonly AppDomain currentDomain = AppDomain.CurrentDomain;

        private IEnumerable<Assembly> _domainAssemblies;

        public AssemblyLoader()
        {
            // 存储加载的程序集
            _executingPath = Assembly.GetExecutingAssembly().Location;
            _fileInfo = new FileInfo(_executingPath).Directory;

            // 返回执行目录中所有DLL的列表
            _assemblies = GetFiles(_fileInfo);
            _domainAssemblies = currentDomain.GetAssemblies().Where(a => !a.IsDynamic);

            AppDomain.CurrentDomain.AssemblyResolve += LoadApplicationAssemblies;
        }
        /// <summary>
        /// 从指定路径加载
        /// </summary>
        public AssemblyLoader(string pPath)
        {
            // 指定路径
            _executingPath = pPath;
            _fileInfo = new FileInfo(_executingPath).Directory;

            // 返回执行目录中所有DLL的列表
            _assemblies = GetFiles(_fileInfo);
            _domainAssemblies = currentDomain.GetAssemblies().Where(a => !a.IsDynamic);

            AppDomain.CurrentDomain.AssemblyResolve += LoadApplicationAssemblies;
        }
        /// <summary>
        /// 返回程序集的事件处理程序
        /// </summary>
        /// <returns>程序集的名称</returns>
        public Assembly LoadApplicationAssemblies(object sender, ResolveEventArgs args)
        {
            if (string.IsNullOrEmpty(_executingPath))
                return null;

            try
            {
                // 忽略缺少的资源
                if (args.Name.Contains(".resources"))
                    return null;

                // 检查是否已加载程序集
                Assembly loadedAssembly = _domainAssemblies.FirstOrDefault(x => x.FullName == args.Name);
                if (loadedAssembly != null)
                    return loadedAssembly;

                var requestedAssembly = args.Name.Split(',')[0];
                var assemblyToLoad = _assemblies.Where(x => x.Contains(requestedAssembly)).FirstOrDefault();

                return Assembly.LoadFrom(assemblyToLoad);
            }

            catch (Exception e)
            {
                return null;
            }
        }

        public void Dispose()
        {
            AppDomain.CurrentDomain.AssemblyResolve -= LoadApplicationAssemblies;
        }
    }
}

解决方案:

在加载程序集前注册事件AppDomain.CurrentDomain.AssemblyResolve,加载失败的的时候触发。获取指定路径的文件列表,判断是否已经加载了,未加载的从指定路径加载。加载完成后别忘了Dispose掉。

 这是在用wpf做插件的时候发现的问题,衍生的问题还有wpf制作插件,然后通过这个获取共享盘上的资源文件。还有在做大型项目的时候将所有dll,放在一个文件夹中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值