我遇到的情况是,我正在创建一个使用另一个第三方DLL的DLL,但我希望能够将第三方DLL构建到我的DLL中,而不是尽可能将它们保持在一起。
这是C#和.NET 3.5。
我要这样做的方式是将第三方DLL存储为嵌入式资源,然后在执行第一个DLL时将其放置在适当的位置。
我最初计划执行此操作的方法是编写代码以将第三方DLL放在System.Reflection.Assembly.GetExecutingAssembly().Location.ToString() 减去最后一个指定的位置/nameOfMyAssembly.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的代码部分时,找不到它。
有人对我需要做些不同的事情有任何想法吗?
将第三方程序集作为资源嵌入后,AppDomain.AssemblyResolve在应用程序启动期间添加代码以订阅当前域的事件。只要CLR的Fusion子系统未能根据有效的探测(策略)找到程序集,就会触发此事件。在的事件处理程序中AppDomain.AssemblyResolve,使用加载资源,Assembly.GetManifestResourceStream并将其内容作为字节数组送入相应的Assembly.Load重载。以下是一种这样的实现在C#中的样子:
AppDomain.AssemblyResolve
Assembly.GetManifestResourceStream
Assembly.Load
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可以定义为:
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可能是另一个可以考虑的选择,尽管它涉及更多。