欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#如何將DLL打包到程序中

 更新時(shí)間:2023年01月24日 14:38:18   作者:Danny_hi  
這篇文章主要介紹了C#如何將DLL打包到程序中問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

C#將DLL打包到程序中

有時(shí)候我們的程序中包含一些添加的DLL文件,使用起來(lái)不方便,我們可以把這些DLL文件打包到程序集中,只剩下一個(gè)EXE文件: 

舉例

我先寫(xiě)一個(gè)DLL的庫(kù),里面只有一個(gè)加法運(yùn)算:

namespace ClassCal
{
    public class Calculate
    {
        public int TestAdd(int num1,int num2)
        {
            return num1 + num2;
        }
    }
}

然后在Winform項(xiàng)目中引用這個(gè)類庫(kù),實(shí)現(xiàn)一個(gè)加法運(yùn)算:

private void btn_cal_Click(object sender, EventArgs e)
{
     ClassCal.Calculate t1 = new ClassCal.Calculate();
     int value = t1.TestAdd(Convert.ToInt32(tb_num1.Text), Convert.ToInt32(tb_num2.Text));

     tb_sum.Text = value.ToString();
}

運(yùn)行效果:

生成一個(gè)可執(zhí)行程序exe文件,但里面包含一個(gè)ClassCal.dll類庫(kù)文件;顯然,如果想要把這個(gè)程序發(fā)給別人使用,一定要帶上這個(gè)類庫(kù)文件;

現(xiàn)在可以用下面的方法,將類庫(kù)打包到應(yīng)用程序中:

首先在應(yīng)用程序中添加需要引用的類庫(kù)文件,將其屬性改為嵌入的資源;

就可以在硬盤(pán)加載失敗的時(shí)候 從資源文件中加載對(duì)應(yīng)的dll,如下代碼:

static class Program
    {

        static Program()
        {
            //這個(gè)綁定事件必須要在引用到ClassCal這個(gè)程序集的方法之前,注意是方法之前,不是語(yǔ)句之間,就算語(yǔ)句是在方法最后一行,在進(jìn)入方法的時(shí)候就會(huì)加載程序集,如果這個(gè)時(shí)候沒(méi)有綁定事件,則直接拋出異常,或者程序終止了
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }

        static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            //獲取加載失敗的程序集的全名
            var assName = new AssemblyName(args.Name).FullName;
            if (args.Name == "ClassCal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
            {
                //讀取資源
                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("WinFormTest.ClassCal.dll"))
                {
                    var bytes = new byte[stream.Length];
                    stream.Read(bytes, 0, (int)stream.Length);
                    return Assembly.Load(bytes);//加載資源文件中的dll,代替加載失敗的程序集
                }
            }
            throw new DllNotFoundException(assName);
        }
        /// <summary>
        /// 應(yīng)用程序的主入口點(diǎn)。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

這樣程序就可以以一個(gè)EXE單獨(dú)運(yùn)行了;

。。。。

如果有很多DLL怎么辦,可以寫(xiě)一個(gè)通用的DLL加載類:

原理蠻簡(jiǎn)單的,主要是通過(guò)StackTrace類獲取調(diào)用RegistDLL方法的對(duì)象,獲取到對(duì)方的程序集,

然后通過(guò)Assembly.GetManifestResourceNames()獲取所有資源的名稱,

判斷后綴名".dll"(這一步可以自由發(fā)揮),然后加載,以加載的程序集的名稱為key保存到一個(gè)字典中,

并綁定AppDomain.AssemblyResolve事件,

在程序集加載失敗時(shí),從字典中查詢同名程序集,如果有,直接從字典中加載:

/// <summary> 載入資源中的動(dòng)態(tài)鏈接庫(kù)(dll)文件
    /// </summary>
    static class LoadResourceDll
    {
        static Dictionary<string, Assembly> Dlls = new Dictionary<string, Assembly>();
        static Dictionary<string, object> Assemblies = new Dictionary<string, object>();

        static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
        {
            //程序集
            Assembly ass;
            //獲取加載失敗的程序集的全名
            var assName = new AssemblyName(args.Name).FullName;
            //判斷Dlls集合中是否有已加載的同名程序集
            if (Dlls.TryGetValue(assName, out ass) && ass != null)
            {
                Dlls[assName] = null;//如果有則置空并返回
                return ass;
            }
            else
            {
                throw new DllNotFoundException(assName);//否則拋出加載失敗的異常
            }
        }

        /// <summary> 注冊(cè)資源中的dll
        /// </summary>
        public static void RegistDLL()
        {
            //獲取調(diào)用者的程序集
            var ass = new StackTrace(0).GetFrame(1).GetMethod().Module.Assembly;
            //判斷程序集是否已經(jīng)處理
            if (Assemblies.ContainsKey(ass.FullName))
            {
                return;
            }
            //程序集加入已處理集合
            Assemblies.Add(ass.FullName, null);
            //綁定程序集加載失敗事件(這里我測(cè)試了,就算重復(fù)綁也是沒(méi)關(guān)系的)
            AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
            //獲取所有資源文件文件名
            var res = ass.GetManifestResourceNames();
            foreach (var r in res)
            {
                //如果是dll,則加載
                if (r.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        var s = ass.GetManifestResourceStream(r);
                        var bts = new byte[s.Length];
                        s.Read(bts, 0, (int)s.Length);
                        var da = Assembly.Load(bts);
                        //判斷是否已經(jīng)加載
                        if (Dlls.ContainsKey(da.FullName))
                        {
                            continue;
                        }
                        Dlls[da.FullName] = da;
                    }
                    catch
                    {
                        //加載失敗就算了...
                    }
                }
            }
        }
    }

然后在主程序前加載一下這個(gè)程序集即可:

static class Program
    {
        static Program()
        {
            LoadResourceDll.RegistDLL();
        }

        /// <summary>
        /// 應(yīng)用程序的主入口點(diǎn)。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論