[C#]載入 自訂資料夾裡的 DLL 組件(.net dll)

  • 2985
  • 0
  • C#
  • 2016-10-27

摘要:[C#] Load DLL(Assembly) from a specific folder (.net dll)

 

使用說明:

1.在使用前請先透過'加入參考'加入 System.Configuration 組件

 

2.在 App.config 加入下列,並設定自訂 DLL 資料夾的路徑。

<configuration>
  <appSettings>
    <add key="DllPrivatePath" value="myDLLFolder1;myDLLFolder2/myDLLFolder22;myDLLFolder3"/>
  </appSettings>
</configuration>

 

3.在主程式類別(Program Class)手動加入'靜態建構函式',並在該函式裡面'加入下段程式碼'

class Program
{
    /// <summary>
    /// 加入此段程式碼
    /// </summary>
    static Program()
    {
        LoadAssemblys.LoadAssembly.AddAssemblyPrivatePath();
    }

    static void Main(string[] args)
    {
        //That new Private Path DLL Assembly class ....
    }
}

 

LoadAssembly 類別的原始碼:

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;

namespace LoadAssemblys
{
    internal static class LoadAssembly
    {
        private readonly static object _regAddAssemblyPrivatePathLock = new object();

        /// <summary>
        /// 是否已設定(掛載)過解析'自訂 DLL 資料夾'功能
        /// </summary>
        private static bool _hasRegAddAssemblyPrivatePath = false;

        /// <summary>
        /// 設定(掛載)能解析'自訂 DLL 資料夾'內的 DLL 組件功能
        /// </summary>
        public static void AddAssemblyPrivatePath()
        {
            if (_hasRegAddAssemblyPrivatePath)
            {
                return;
            }

            lock (_regAddAssemblyPrivatePathLock)
            {
                if (!_hasRegAddAssemblyPrivatePath)
                {
                    AppDomain.CurrentDomain.AssemblyResolve += AssemblyPrivatePath;
                    _hasRegAddAssemblyPrivatePath = true;
                }
            }
        }

        /// <summary>
        /// 解析'自訂 DLL 資料夾'內的 DLL 組件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        /// <returns>回傳所需的 DLL 組件</returns>
        private static Assembly AssemblyPrivatePath(object sender, ResolveEventArgs args)
        {
            var addedAssmbs = AppDomain.CurrentDomain.GetAssemblies();
            var someAssmb = addedAssmbs.FirstOrDefault(x => x.FullName == args.Name);
            if (someAssmb != null)
            {
                return someAssmb;
            }

            var assmbPaths = _dllPrivatePath.Value;
            if (!assmbPaths.Any())
            {
                return null;
            }

            var assmbName = new AssemblyName(args.Name).Name;
            Assembly executingAssemblies = Assembly.GetExecutingAssembly();
            AssemblyName[] referencedAssmbNames = executingAssemblies.GetReferencedAssemblies();
            foreach (AssemblyName refAssmbName in referencedAssmbNames)
            {
                if (new AssemblyName(refAssmbName.Name).Name == assmbName)
                {
                    foreach (var path in assmbPaths)
                    {
                        var dllFullPath = Path.Combine(path, assmbName + ".dll");
                        if (File.Exists(dllFullPath))
                        {
                            return Assembly.LoadFrom(dllFullPath);
                        }
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 取得'自訂 DLL 資料夾'路徑
        /// </summary>
        private readonly static Lazy<string[]> _dllPrivatePath = new Lazy<string[]>(DllPrivatePathCore);

        /// <summary>
        /// 解析 App.config 裡 AppSettings 資料的 DllPrivatePath 值(路徑)
        /// </summary>
        /// <returns>解析後的值(路徑)</returns>
        private static string[] DllPrivatePathCore()
        {
            var appDir = AppDomain.CurrentDomain.BaseDirectory;
            var dllPrivatePath = ConfigurationManager.AppSettings["DllPrivatePath"];
            if (!string.IsNullOrEmpty(dllPrivatePath) && !string.IsNullOrEmpty(appDir))
            {
                return dllPrivatePath.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
                                     .Select(x => Path.Combine(appDir, x.TrimEnd('\\', '/')) + @"\")
                                     .ToArray();
            }

            return new string[0];
        }
    }
}

 

主要參考:

AppDomain.AssemblyResolve Event Tips​
C# - Load Assembly from Specific Directory Path

※在此感謝所有的幫助者,感謝~