如果您创建一个类库,它使用来自其他程序集的东西,是否可以将这些其他程序集作为某种资源嵌入到类库中?
也就是说,不是让MyAssembly.dll、SomeAssembly1.dll和SomeAssembly2.dll坐在文件系统上,而是将另外两个文件绑定到MyAssembly.dll中并在其代码中使用。
我也有点不明白为什么.NET程序集是.dll文件。这种格式不是在.NET之前就存在了吗?是否所有.NET程序集DLL,但并非所有DLL都是.NET程序集?为什么他们使用相同的文件格式和/或文件扩展名?
发布于 2008-10-21 17:11:05
查看用于合并程序集的ILMerge。
我也有点不明白为什么.NET程序集是.dll文件。这种格式不是在.NET之前就存在了吗?
是。
是所有.NET程序集DLL,
通常情况下,DLL或EXE -但也可以是netmodule。
但不是所有all都是.NET程序集吗?
对,是这样。
为什么他们使用相同的文件格式和/或文件扩展名?
为什么它会有任何不同-它的目的是相同的!
发布于 2009-03-09 05:27:20
ILMerge确实合并了程序集,这很好,但有时并不完全符合您的要求。例如,当所讨论的程序集是一个强名称的程序集,并且您没有该程序集的密钥时,您就不能在不破坏该签名的情况下执行ILMerge。这意味着您必须部署多个程序集。
可以将一个或多个程序集作为资源嵌入到您的exe或DLL中,以替代ilmerge。然后,在运行时,当加载程序集时,您可以以编程方式提取嵌入式程序集,并加载并运行它。这听起来很棘手,但只有一点点样板代码。
为此,嵌入程序集,就像嵌入任何其他资源(图像、翻译文件、数据等)一样。然后,设置一个在运行时调用的AssemblyResolver。应该在启动类的静态构造函数中设置它。代码非常简单。
static NameOfStartupClassHere()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
}
static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
Assembly a1 = Assembly.GetExecutingAssembly();
Stream s = a1.GetManifestResourceStream(args.Name);
byte[] block = new byte[s.Length];
s.Read(block, 0, block.Length);
Assembly a2 = Assembly.Load(block);
return a2;
}ResolveEventArgs参数上的Name属性是要解析的程序集的名称。此名称引用的是资源,而不是文件名。如果嵌入名为"MyAssembly.dll“的文件,并调用嵌入的资源"Foo",那么这里需要的名称是"Foo”。但是这会让人感到困惑,所以我建议使用程序集的文件名作为资源的名称。如果已正确嵌入和命名程序集,则只需使用程序集名称调用GetManifestResourceStream()并以这种方式加载程序集。非常简单。
这适用于多个程序集,与单个嵌入式程序集一样好。
在一个真正的应用程序中,你会想要更好地处理这个例程中的错误--比如,如果没有给定名称的流呢?如果读取失败会发生什么?等等,但那是留给你去做的。
在其余的应用程序代码中,您通常使用来自程序集的类型。
当您构建应用程序时,您需要像通常那样添加对程序集的引用。如果使用命令行工具,请在/r中使用csc.exe选项;如果使用Visual,则需要“添加引用.”在项目的弹出菜单中。
在运行时,程序集版本检查和验证工作如常.
唯一的区别是分配。在部署或分发应用程序时,不需要为嵌入式(和引用)程序集分发DLL。只需部署主程序集;不需要分发其他程序集,因为它们嵌入到主DLL或EXE中。
发布于 2008-10-21 17:11:24
可以将程序集(或任何文件)作为资源嵌入(然后使用ResourceManager类访问它们),但是如果您只想组合程序集,最好使用像ILMerge这样的工具。
EXE和DLL文件是Windows可移植可执行文件,它们足够通用,可以容纳未来类型的代码,包括任何.NET代码(它们也可以在DOS中运行,但只显示一条消息,说明它们不应该在DOS中运行)。它们包括在.NET运行时尚未运行时启动它的指令。一个程序集也有可能跨越多个文件,尽管这种情况很少发生。
https://stackoverflow.com/questions/222655
复制相似问题