C# / WPF dll 嵌入

前言

构建应用时常常有生成单个文件的需要,在 .NET Core 中发布程序有生成单个文件的选项,但如果不得不使用 .NET Framework ,也不是没有办法实现生成单个文件。

正文

不需要 ILMerge 或者 ILRepack 等工具,且这些工具常常麻烦且失效。

以 WPF 为例,在写完程序后,先把 NuGet 包或者自己的 dll 文件丢到项目中,并修改生成操作为嵌入的资源

然后订阅 AppDomain.CurrentDomain.AssemblyResolve 事件,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string resources = null;
foreach (var item in dlls)
{
if (args.Name.StartsWith(item))
{
resources = item + ".dll";
break;
}
}

if (string.IsNullOrEmpty(resources))
{
return null;
}

var assembly = Assembly.GetExecutingAssembly();
resources = assembly.GetManifestResourceNames().FirstOrDefault(s => s.EndsWith(resources));

if (string.IsNullOrEmpty(resources))
{
return null;
}

using (Stream stream = assembly.GetManifestResourceStream(resources))
{
if (stream == null)
{
return null;
}

var block = new byte[stream.Length];
stream.Read(block, 0, block.Length);
return Assembly.Load(block);
}
}

这时我们就可以在引用中关闭复制到本地了,不出意外的话程序仍能够正常运行

注意

大多程序集可以这么操作,但也有一些例外,如 Prism 的程序集内置就会报错,这个可以自行尝试。