1.第一步:通过 NuGet 安装 Costura.Fody
和 Fody
再添加一个Newtonsoft.Json的包测试
项目重新生成后 DLL自动打包到EXE里
根目录自动创建 FodyWeavers.xml
文件
2.FodyWeavers.xml
配置文件
FodyWeavers.xml
是配置文件,通过修改CosturaFodyWeavers.xml
中的节点来访问所有配置选项,默认配置如下,
<Weavers>
<Costura/></Weavers>
1)CreateTemporaryAssemblies
将嵌入的文件复制到磁盘,然后再将它们加载到内存中。对于要从物理文件加载程序集的某些场景很有用。默认为false。
<Costura CreateTemporaryAssemblies='true' />
2)IncludeDebugSymbols
配置是否还嵌入引用程序集的.pdb文件,默认为true。
<Costura IncludeDebugSymbols='false' />
3)IncludeRuntimeReferences
配置.NET Core所使用的内嵌依赖项的运行时文件夹是否被内嵌。默认为true。
<Costura IncludeRuntimeReferences='false' />
4)UseRuntimeReferencePaths
配置运行时程序集是嵌入其完整路径还是只嵌入其程序集名称。.NET Framework项目默认为false,.NET Core项目默认为true。
<Costura UseRuntimeReferencePaths='true' />
5)DisableCompression
默认情况下,嵌入式程序集是压缩的,加载时则不压缩。可以使用此选项关闭压缩。
<Costura DisableCompression='true' />
6)DisableCleanup
作为Costura的一部分,嵌入式组件不再包含在构建中。这种Cleanup可以关闭。默认为false。
<Costura DisableCleanup='true' />
7)LoadAtModuleInit
默认情况下,Costura将作为模块初始化的一部分加载。该选项禁用该行为。确保在代码的某个地方调用了CosturaUtility.Initialize()。默认为true。
<Costura LoadAtModuleInit='false' />
8)IgnoreSatelliteAssemblies
默认情况下,Costura
将使用名为’resources.dll
’的程序集作为附属资源,并将输出路径放在前面。该配置项禁用该行为。
DLL项目程序集名称以’.resources
’结尾,当设置为false
时,*.resources.dll
将导致错误。默认为false
,配置如下,
<Costura IgnoreSatelliteAssemblies='true' />
9)ExcludeAssemblies / ExcludeRuntimeAssemblies
要从默认操作 “嵌入所有复制本地引用” 中排除的程序集名称列表。
不要在名称中包含.exe或.dll。
不能用IncludeAssemblies
定义。
可以对部分程序集名称匹配使用通配符。例如,System.将排除所有以System.开头的程序集。通配符只能在条目的末尾使用,因此,例如,System..Private.*将不起作用。
可以使用多行配置:
<Costura>
<ExcludeAssemblies>
Foo
Bar
</ExcludeAssemblies>
</Costura>
或者配置在一行使用|分隔,如下,
<Costura ExcludeAssemblies='Foo|Bar' />
10)IncludeAssemblies / IncludeRuntimeAssemblies
从默认操作“嵌入所有复制本地引用”中包含的程序集名称列表。
不要在名称中包含.exe或.dll。
不能用ExcludeAssemblies / incluuntimeassemblies
定义。
可以在名称的末尾使用通配符进行部分匹配。
可以使用多行配置:
<Costura>
<IncludeAssemblies>
Foo
Bar </IncludeAssemblies></Costura>
或者配置在一行使用|分隔,如下,
<Costura IncludeAssemblies='Foo|Bar' />
10)Unmanaged32Assemblies
和 Unmanaged64Assemblies
不能以与托管程序集相同的方式加载非托管程序集。
为了帮助Costura
识别哪些程序集是Mixed-mode
,以及在什么环境中加载它们,应该将它们的名称包含在一个或两个列表中。
不要在名称中包含.exe或.dll。
可以在名称的末尾使用通配符进行部分匹配。
可以使用多行配置:
<Costura>
<Unmanaged32Assemblies>
Foo32
Bar32 </Unmanaged32Assemblies>
<Unmanaged64Assemblies>
Foo64
Bar64 </Unmanaged64Assemblies></Costura>
或者配置在一行使用|分隔,如下,
<Costura
Unmanaged32Assemblies='Foo32|Bar32'
Unmanaged64Assemblies='Foo64|Bar64' />
3、配置预加载程序集顺序
Costura
可以自动加载本地库。要包含本机库,请将其作为嵌入式资源包含在项目中称为costura32
或costura64
的文件夹中,这取决于库的bittyness
。
还可以选择指定预加载库的加载顺序。当从磁盘混合模式使用临时程序集时,程序集也会被预加载。
要指定预加载程序集的顺序,请向配置中添加PreloadOrder
元素。
可以使用多行配置:
<Costura>
<PreloadOrder>
Foo
Bar </PreloadOrder></Costura>
或者配置在一行使用|分隔,如下,
<Costura PreloadOrder='Foo|Bar' />
4、CosturaUtility
CosturaUtility
是一个类,它允许在自己的代码中手动初始化Costura
系统。主要用于模块初始化器不起作用的场景,比如库和Mono
。
要使用,请在代码中尽可能早地调用CosturaUtility.Initialize()
。例如,
class Program
{
static Program()
{
CosturaUtility.Initialize();
}
static void Main(string[] args) { ... }
}
5、单元测试框架
大多数单元测试框架需要.dll文件来发现和执行单元测试。可能需要将如下配置添加到测试组件中。
<Weavers>
<Costura ExcludeAssemblies='TargetExe|TargetExeTest'
CreateTemporaryAssemblies='true'
DisableCleanup='true'/></Weavers>
6、读取Costura.Fody
内嵌压缩的程序集
合成之后被压缩的程序集需要读取,可以参考如下代码,
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp1
{
class Program
{
static void CopyTo(Stream source, Stream destination)
{
int count;
var array = new byte[81920];
while ((count = source.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
static Stream LoadStream(string fullname)
{
FileStream stream = default(FileStream);
if (fullname.EndsWith(".zip"))
{
using (stream = new FileStream(fullname, FileMode.Open))
{
using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress))
{
var memStream = new MemoryStream();
CopyTo(compressStream, memStream);
memStream.Position = 0;
return memStream;
}
}
}
return stream;
}
static void Main(string[] args)
{
Stream stream;
Stream file;
string RefilePath = @"^.+[^\\]+\\";
string fullname;
string newFile;
for (int i = 0; i < args.Count(); i++)
{
fullname = args[i];
newFile = Regex.Replace(fullname, "\\.zip$", string.Empty);
Console.Write("{0} -> {1}\r\n",
Regex.Replace(fullname, RefilePath, string.Empty),
Regex.Replace(newFile, RefilePath, string.Empty));
try
{
stream = LoadStream(fullname);
using (file = File.Create(newFile))
{
CopyTo(stream, file);
}
}
catch (Exception ex)
{
Console.Write("{0}", ex.ToString());
}
}
}
}
}
注意:如果其它静态的资源文件,可以在VS中文件属性"生成操作" 选择 “Resource”,然后在读取资源文件。