问题描述
我遇到了一种情况,我正在创建一个使用另一个第三方 DLL 的 DLL,但我更希望能够将第三方 DLL 构建到我的 DLL 中,而不必将它们放在一起,如果可能.
I've got a situation where I have a DLL I'm creating that uses another third party DLL, but I would prefer to be able to build the third party DLL into my DLL instead of having to keep them both together if possible.
这是 C# 和 .NET 3.5.
This with is C# and .NET 3.5.
我想这样做的方法是将第三方 DLL 存储为嵌入式资源,然后在执行第一个 DLL 期间将其放置在适当的位置.
The way I would like to do this is by storing the third party DLL as an embedded resource which I then place in the appropriate place during execution of the first DLL.
我最初计划这样做的方式是编写代码将第三方 DLL 放在 System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()
指定的位置减去最后一个 /nameOfMyAssembly.dll
.我可以在这个位置成功保存第三方 .DLL
(最终是
The way I originally planned to do this is by writing code to put the third party DLL in the location specified by System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()
minus the last /nameOfMyAssembly.dll
. I can successfully save the third party .DLL
in this location (which ends up being
C:Documents and SettingsmyUserNameLocal SettingsApplication数据组装dl3KXPPAX6Y.ZCYA1MZ1499.1TRe0115d4491bb86eb_fe18c901
),但是当我到达需要此 DLL 的代码部分时,它找不到它.
), but when I get to the part of my code requiring this DLL, it can't find it.
有人知道我需要做些什么不同的事情吗?
Does anybody have any idea as to what I need to be doing differently?
推荐答案
将第三方程序集作为资源嵌入后,添加代码以订阅 AppDomain.AssemblyResolve
应用程序启动期间当前域的事件.每当 CLR 的 Fusion 子系统无法根据有效的探测(策略)定位程序集时,就会触发此事件.在 AppDomain.AssemblyResolve
的事件处理程序中,使用 Assembly.GetManifestResourceStream
并将其内容作为字节数组提供给相应的 Assembly.Load
重载.下面是一个这样的实现在 C# 中的样子:
Once you've embedded the third-party assembly as a resource, add code to subscribe to the AppDomain.AssemblyResolve
event of the current domain during application start-up. This event fires whenever the Fusion sub-system of the CLR fails to locate an assembly according to the probing (policies) in effect. In the event handler for AppDomain.AssemblyResolve
, load the resource using Assembly.GetManifestResourceStream
and feed its content as a byte array into the corresponding Assembly.Load
overload. Below is how one such implementation could look like in 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 可能是另一种选择考虑一下,尽管涉及更多.
Finally, as a few have already mentioned, ILMerge may be another option to consider, albeit somewhat more involved.
这篇关于将一个 dll 作为嵌入资源嵌入另一个中,然后从我的代码中调用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!