利用反射动态调用C#嵌入到资源的托管DLL

以前写了一篇博客《C#嵌入dll到资源释放的问题》讲到了DLL文件嵌入到资源后,程序运行时自动释放并实现代码调用的问题。很多读者都问到了同一个问题:文章针对的是非托管的Win 32 DLL,那么托管的DLL怎么嵌入并释放呢?这篇文章就来聊一下这个话题。

由于托管应用程序在启动时就需要加载全部使用到的托管DLL,所以采用嵌入Win32 DLL到资源然后再释放的方式是不可行的。有一种思路是在生成EXE后,把需要调用的DLL与EXE合并成一个新的EXE,比如IMerge等工具就可以实现这一过程(其实我也一直这么干)。但是今天我要讲的是一种类似嵌入非托管DLL的方式,利用反射直接通过代码来实现动态调用。

1 引用DLL

需要调用的托管math.dll主要代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace math
{
    public class math
    {
        public static int add(int a, int b)
        {
            return a + b;
        }
    }
}

生成math.dll后,在需要调用的C#程序中添加对math.dll的引用:

利用反射动态调用C#嵌入到资源的托管DLL_第1张图片

2 嵌入DLL

具体嵌入步骤:

  1. 将引用的math修改属性:复制本地->False。

    利用反射动态调用C#嵌入到资源的托管DLL_第2张图片

  2. 将math.dll文件加入到调用程序功能的资源中,注意修改属性:生成操作->嵌入的资源。

    利用反射动态调用C#嵌入到资源的托管DLL_第3张图片

3 反射DLL

直接上代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using System.IO;

namespace Demo
{
    static class Program
    {
        /// 
        /// 应用程序的主入口点。
        /// 
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //反射
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
            Application.Run(new Form1());
        }

        static Assembly CurrentDomain_AssemblyResolve(object sender, EventArgs e)
        {
            //从资源中加载DLL到内存
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Demo.math.dll"))
            {
                byte[] byData = new byte[stream.Length];
                stream.Read(byData, 0, byData.Length);
                return Assembly.Load(byData);
            }
        }
    }
}

我们现在就可以删除math.dll文件,直接运行生成的EXE程序,过程就这么简单。

你可能感兴趣的:(.NET)