C#动态加载嵌入的资源dll-【解决一些异常加载问题】

在有这个需求时,在网上搜索了许多这方面的资料,结果是网上的方法并不适用我的项目。其实网上的方法是对的,但由于未考虑一些问题,所以导致在我的项目不成功。现将我优化过的方法提供如下【不明白看代码注释】:

首先说明个问题,C#动态加载dll,也即内存加载dll,通常包括两种情况,加载C++的dll和C#的dll,本文阐述的是后者。

// 综述:本例中,我要通过内存加载的程序集是x4lib,并使用其中的一个类ProcPiper。
// 把握要点:尽可能的让CurrentDomain_AssemblyResolve在程序启动的最初就被执行。
// 代码不多,请耐心看,理解之,欲速则不达

    static class Program
    {
        // 1.此函数会在Main执行前执行,这样使得dll加载事件尽可能在程序启动的最初就被注册;
        static Program()
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }

        // 2.网上的方案在我这个项目行不通正是因为这行代码,因为我声明了一个全局静态且包含在被嵌入的dll中的一个类对象。解决方法看2'
        // public static x4lib.ProcPiper _Piper = null;

        // 2'.解决方法:将类型x4lib.ProcPiper改为object,并设置为属性方式;
        private static object _Piper = null;
        public static x4lib.ProcPiper Piper
        {
            get { return (x4lib.ProcPiper)_Piper; }
        }
        

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Program._Piper = new x4lib.ProcPiper();

            // 启动C#端ProcPiper
            new Thread(new ThreadStart(delegate()
            {
                Program.Piper.Exec(1024);
            })).Start();


            Application.Run(form1);
            Program.Piper.Exit();
        }

        private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            // 使用方法:
            // 1.将dll通过“添加引用”加到当前项目;
            // 2.将dll添加为资源文件,同时设为“嵌入的资源”;
            // 3.通过事件的方式,使程序在Main执行前触发此事件;
            // 注意事项:
            // 1.不可以在当前项目直接定义被嵌入的dll中的静态全局对象

            string strNameSpace = MethodBase.GetCurrentMethod().DeclaringType.Namespace;
            string strResources = "Resources";
            string strPrefix = strNameSpace + "." + strResources + ".";
            string strCSharpDll = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";

            Assembly assembly = Assembly.GetExecutingAssembly();
            string[] strRess = assembly.GetManifestResourceNames();
            foreach (string it in strRess)
            {
                string strRes = it.Substring(strPrefix.Length);
                if (strRes.Equals(strCSharpDll))
                {
                    using (var tmp = assembly.GetManifestResourceStream(it))
                    {
                        byte[] buf = new byte[tmp.Length];
                        tmp.Read(buf, 0, (int)tmp.Length);
                        return Assembly.Load(buf);
                    }
                }
            }
            return null;
        }
    }

猜你喜欢

转载自blog.csdn.net/xk641018299/article/details/90110269
今日推荐