一尘不染

将一个dll作为嵌入式资源嵌入到另一个dll中,然后从我的代码中调用它

c#

我遇到的情况是,我正在创建一个使用另一个第三方DLL的DLL,但我希望能够将第三方DLL构建到我的DLL中,而不是尽可能将它们保持在一起。

这是C#和.NET 3.5。

我要这样做的方式是将第三方DLL存储为嵌入式资源,然后在执行第一个DLL时将其放置在适当的位置。

我最初计划执行此操作的方法是编写代码以将第三方DLL放在System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()
减去最后一个指定的位置/nameOfMyAssembly.dll。我可以.DLL在该位置成功保存第三方(最终被保存为

C:\ Documents and Settings \ myUserName \ Local Settings \ Application Data
\ assembly \ dl3 \ KXPPAX6Y.ZCY \ A1MZ1499.1TR \ e0115d44 \
91bb86eb_fe18c901

),但是当我到达需要此DLL的代码部分时,找不到它。

有人对我需要做些不同的事情有任何想法吗?


阅读 1024

收藏
2020-05-19

共1个答案

一尘不染

将第三方程序集作为资源嵌入后,AppDomain.AssemblyResolve在应用程序启动期间添加代码以订阅当前域的事件。只要CLR的Fusion子系统未能根据有效的探测(策略)找到程序集,就会触发此事件。在的事件处理程序中AppDomain.AssemblyResolve,使用加载资源,Assembly.GetManifestResourceStream并将其内容作为字节数组送入相应的Assembly.Load重载。以下是一种这样的实现在C#中的样子:

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var resName = args.Name + ".dll";    
    var thisAssembly = Assembly.GetExecutingAssembly();    
    using (var input = thisAssembly.GetManifestResourceStream(resName))
    {
        return input != null 
             ? Assembly.Load(StreamToBytes(input))
             : null;
    }
};

在那里StreamToBytes可以定义为:

static byte[] StreamToBytes(Stream input) 
{
    var capacity = input.CanSeek ? (int) input.Length : 0;
    using (var output = new MemoryStream(capacity))
    {
        int readLength;
        var buffer = new byte[4096];

        do
        {
            readLength = input.Read(buffer, 0, buffer.Length);
            output.Write(buffer, 0, readLength);
        }
        while (readLength != 0);

        return output.ToArray();
    }
}

最后,正如一些人已经提到的那样,ILMerge可能是另一个可以考虑的选择,尽管它涉及更多。

2020-05-19