我们分发了一个DLL,它对其他DLL有外部依赖性。我们将DLL嵌入到我们自己的DLL / EXE中,并在运行时加载它以满足运行时链接,而不是冒着丢失DLL或潜在混合匹配情况的风险。
的问题: 的
A)
之间哪种方法消耗更多内存,大约消耗多少?
B)有没有人有比上述更好的方法?特别是对于下面详细信息中的第3项。
我们感兴趣的流程详情:
在我们知道在调用程序集中的代码之前运行的部分注册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();
}
}
嵌入装配体。这是通过“添加现有项目”到.NET项目=>来完成的。选择.dll =>好。返回并选择.dll并在属性中将“构建操作”更改为“嵌入式资源”。
我们仍然需要添加相同的.DLL作为参考,并且仍然需要在类的顶部使用using ExternalNamespace;
语句。如果没有,则构建过程失败,因为它在编译时无法看到外部DLL代码。因此,作为构建后的操作,我们必须从最终的bin
文件夹中删除.DLL文件(而不是它的嵌入式克隆)。
答案 0 :(得分:2)
正如马克所说。
我只会使用ILMerge将所有内容放在一起。
但它可能不可能,但应该适用于'纯'托管程序集(包括使用unsafe
的程序集)。
答案 1 :(得分:1)
答:只要内部组件本身不具有一些巨大的尺寸(例如一些大型嵌入式资源),它应该可以可接受 - 这是一个有点错误的答案,但是除了“测量它”之外,我没有更好的一个。我偶尔也做过非常类似的事情(并且出于类似的原因)。
B:在参考属性( f4 )上将“复制本地”设置为False
。即使文件位于同一个项目中,您也需要using ExternalNamespace;
- 这只会使命名空间发挥作用。