DLL嵌入.NET DLL / EXE时内存和CPU的影响?

时间:2013-04-05 00:07:20

标签: .net performance dll

我们分发了一个DLL,它对其他DLL有外部依赖性。我们将DLL嵌入到我们自己的DLL / EXE中,并在运行时加载它以满足运行时链接,而不是冒着丢失DLL或潜在混合匹配情况的风险。

问题:

A)

之间
  • 将DLL嵌入我们的.EXE / .DLL中,然后在运行时将其加载到内存中 和
  • 将DLL保存为文件系统上的单独文件,然后让系统为我们加载

哪种方法消耗更多内存,大约消耗多少?

B)有没有人有比上述更好的方法?特别是对于下面详细信息中的第3项。


我们感兴趣的流程详情:

  1. 在我们知道在调用程序集中的代码之前运行的部分注册AssemblyResolve事件(例如:init time)

    public void SomeInitCode()
    {
        ...
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            string[] assemblyDetail = args.Name.Split(',');
            var assemblyName= assemblyDetail[0] + ".dll";
    
            var thisAssembly = Assembly.GetExecutingAssembly();
            var allResourceNames = thisAssembly.GetManifestResourceNames();
    
            string requiredResName = allResourceNames.SingleOrDefault(a => a.EndsWith(assemblyName));
    
            using (var input = thisAssembly.GetManifestResourceStream(requiredResName))
            {
                return input != null
                     ? Assembly.Load(StreamToBytes(input))
                     : null;
            }
        };
        ...
    }
    
    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();
        }
    }
    
  2. 嵌入装配体。这是通过“添加现有项目”到.NET项目=>来完成的。选择.dll =>好。返回并选择.dll并在属性中将“构建操作”更改为“嵌入式资源”。

  3. 我们仍然需要添加相同的.DLL作为参考,并且仍然需要在类的顶部使用using ExternalNamespace;语句。如果没有,则构建过程失败,因为它在编译时无法看到外部DLL代码。因此,作为构建后的操作,我们必须从最终的bin文件夹中删除.DLL文件(而不是它的嵌入式克隆)。

2 个答案:

答案 0 :(得分:2)

正如马克所说。

我只会使用ILMerge将所有内容放在一起。

但它可能不可能,但应该适用于'纯'托管程序集(包括使用unsafe的程序集)。

答案 1 :(得分:1)

答:只要内部组件本身不具有一些巨大的尺寸(例如一些大型嵌入式资源),它应该可以可接受 - 这是一个有点错误的答案,但是除了“测量它”之外,我没有更好的一个。我偶尔也做过非常类似的事情(并且出于类似的原因)。

B:在参考属性( f4 )上将“复制本地”设置为False。即使文件位于同一个项目中,您也需要using ExternalNamespace; - 这只会使命名空间发挥作用。