[{"data":1,"prerenderedAt":723},["ShallowReactive",2],{"page-\u002Fcsharp\u002Fwpf\u002F程序集合并dll":3},{"id":4,"title":5,"body":6,"description":70,"extension":716,"meta":717,"navigation":718,"path":719,"seo":720,"stem":721,"__hash__":722},"content\u002Fcsharp\u002FWPF\u002F程序集合并dll.md","程序集合并（Costura.Fody）详解",{"type":7,"value":8,"toc":685},"minimark",[9,13,17,21,24,27,56,59,64,88,92,248,251,255,279,283,303,307,321,325,339,342,346,403,409,420,424,475,479,545,548,552,563,567,575,579,587,591,599,602,606,636,640,660,664,675,678,681],[10,11,5],"h1",{"id":12},"程序集合并costurafody详解",[14,15,16],"h2",{"id":16},"什么是程序集合并",[18,19,20],"p",{},"​\t程序集合并（Assembly Merging）是一种将多个.NET程序集（DLL文件）合并到单个可执行文件中的技术。Costura.Fody是.NET生态系统中最流行的程序集合并工具之一，它通过Fody框架在编译时自动将依赖的DLL嵌入到主程序集中，实现\"单文件部署\"的目标。",[14,22,23],{"id":23},"工作原理",[18,25,26],{},"Costura.Fody基于Fody框架工作，Fody是一个.NET的编译时织入（Compile-time Weaving）工具。其工作流程如下：",[28,29,30,38,44,50],"ol",{},[31,32,33,37],"li",{},[34,35,36],"strong",{},"编译时分析","：在编译过程中，Fody分析项目及其依赖项",[31,39,40,43],{},[34,41,42],{},"程序集嵌入","：将指定的DLL文件作为资源嵌入到主程序集中",[31,45,46,49],{},[34,47,48],{},"加载器注入","：自动生成程序集加载代码，在运行时从嵌入的资源中加载DLL",[31,51,52,55],{},[34,53,54],{},"透明加载","：应用程序无需修改任何代码，依赖的DLL会被自动加载",[14,57,58],{"id":58},"配置方式",[60,61,63],"h3",{"id":62},"_1-安装nuget包","1. 安装NuGet包",[65,66,71],"pre",{"className":67,"code":68,"language":69,"meta":70,"style":70},"language-xml shiki shiki-themes github-light github-dark","\u003CPackageReference Include=\"Costura.Fody\" Version=\"5.7.0\" \u002F>\n\u003CPackageReference Include=\"Fody\" Version=\"6.6.0\" PrivateAssets=\"all\" \u002F>\n","xml","",[72,73,74,82],"code",{"__ignoreMap":70},[75,76,79],"span",{"class":77,"line":78},"line",1,[75,80,81],{},"\u003CPackageReference Include=\"Costura.Fody\" Version=\"5.7.0\" \u002F>\n",[75,83,85],{"class":77,"line":84},2,[75,86,87],{},"\u003CPackageReference Include=\"Fody\" Version=\"6.6.0\" PrivateAssets=\"all\" \u002F>\n",[60,89,91],{"id":90},"_2-配置文件fodyweaversxml","2. 配置文件（FodyWeavers.xml）",[65,93,95],{"className":67,"code":94,"language":69,"meta":70,"style":70},"\u003C?xml version=\"1.0\" encoding=\"utf-8\"?>\n\u003CWeavers xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n  \u003CCostura>\n    \u003C!-- 包含所有依赖项 -->\n    \u003CIncludeAssemblies>\n      \u003CInclude>Wpf.Ui\u003C\u002FInclude>\n      \u003CInclude>CommunityToolkit.Mvvm\u003C\u002FInclude>\n      \u003CInclude>Microsoft.Extensions.DependencyInjection\u003C\u002FInclude>\n    \u003C\u002FIncludeAssemblies>\n    \n    \u003C!-- 排除不需要的依赖项 -->\n    \u003CExcludeAssemblies>\n      \u003CExclude>System.*\u003C\u002FExclude>\n      \u003CExclude>Microsoft.Win32\u003C\u002FExclude>\n    \u003C\u002FExcludeAssemblies>\n    \n    \u003C!-- 创建临时文件（用于调试） -->\n    \u003CCreateTemporaryAssemblies>false\u003C\u002FCreateTemporaryAssemblies>\n    \n    \u003C!-- 禁用压缩 -->\n    \u003CDisableCompression>false\u003C\u002FDisableCompression>\n    \n    \u003C!-- 禁用清理 -->\n    \u003CDisableCleanup>false\u003C\u002FDisableCleanup>\n  \u003C\u002FCostura>\n\u003C\u002FWeavers>\n",[72,96,97,102,107,113,119,125,131,137,143,149,155,161,167,173,179,185,190,196,202,207,213,219,224,230,236,242],{"__ignoreMap":70},[75,98,99],{"class":77,"line":78},[75,100,101],{},"\u003C?xml version=\"1.0\" encoding=\"utf-8\"?>\n",[75,103,104],{"class":77,"line":84},[75,105,106],{},"\u003CWeavers xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n",[75,108,110],{"class":77,"line":109},3,[75,111,112],{},"  \u003CCostura>\n",[75,114,116],{"class":77,"line":115},4,[75,117,118],{},"    \u003C!-- 包含所有依赖项 -->\n",[75,120,122],{"class":77,"line":121},5,[75,123,124],{},"    \u003CIncludeAssemblies>\n",[75,126,128],{"class":77,"line":127},6,[75,129,130],{},"      \u003CInclude>Wpf.Ui\u003C\u002FInclude>\n",[75,132,134],{"class":77,"line":133},7,[75,135,136],{},"      \u003CInclude>CommunityToolkit.Mvvm\u003C\u002FInclude>\n",[75,138,140],{"class":77,"line":139},8,[75,141,142],{},"      \u003CInclude>Microsoft.Extensions.DependencyInjection\u003C\u002FInclude>\n",[75,144,146],{"class":77,"line":145},9,[75,147,148],{},"    \u003C\u002FIncludeAssemblies>\n",[75,150,152],{"class":77,"line":151},10,[75,153,154],{},"    \n",[75,156,158],{"class":77,"line":157},11,[75,159,160],{},"    \u003C!-- 排除不需要的依赖项 -->\n",[75,162,164],{"class":77,"line":163},12,[75,165,166],{},"    \u003CExcludeAssemblies>\n",[75,168,170],{"class":77,"line":169},13,[75,171,172],{},"      \u003CExclude>System.*\u003C\u002FExclude>\n",[75,174,176],{"class":77,"line":175},14,[75,177,178],{},"      \u003CExclude>Microsoft.Win32\u003C\u002FExclude>\n",[75,180,182],{"class":77,"line":181},15,[75,183,184],{},"    \u003C\u002FExcludeAssemblies>\n",[75,186,188],{"class":77,"line":187},16,[75,189,154],{},[75,191,193],{"class":77,"line":192},17,[75,194,195],{},"    \u003C!-- 创建临时文件（用于调试） -->\n",[75,197,199],{"class":77,"line":198},18,[75,200,201],{},"    \u003CCreateTemporaryAssemblies>false\u003C\u002FCreateTemporaryAssemblies>\n",[75,203,205],{"class":77,"line":204},19,[75,206,154],{},[75,208,210],{"class":77,"line":209},20,[75,211,212],{},"    \u003C!-- 禁用压缩 -->\n",[75,214,216],{"class":77,"line":215},21,[75,217,218],{},"    \u003CDisableCompression>false\u003C\u002FDisableCompression>\n",[75,220,222],{"class":77,"line":221},22,[75,223,154],{},[75,225,227],{"class":77,"line":226},23,[75,228,229],{},"    \u003C!-- 禁用清理 -->\n",[75,231,233],{"class":77,"line":232},24,[75,234,235],{},"    \u003CDisableCleanup>false\u003C\u002FDisableCleanup>\n",[75,237,239],{"class":77,"line":238},25,[75,240,241],{},"  \u003C\u002FCostura>\n",[75,243,245],{"class":77,"line":244},26,[75,246,247],{},"\u003C\u002FWeavers>\n",[14,249,250],{"id":250},"主要优点",[60,252,254],{"id":253},"_1-简化部署","1. 简化部署",[256,257,258,267,273],"ul",{},[31,259,260,263,264],{},[34,261,262],{},"单文件分发","：只需要分发一个exe文件，",[34,265,266],{},"无需担心DLL依赖问题",[31,268,269,272],{},[34,270,271],{},"减少文件数量","：避免部署时遗漏依赖文件的情况",[31,274,275,278],{},[34,276,277],{},"降低部署复杂度","：特别适合需要分发给最终用户的桌面应用程序",[60,280,282],{"id":281},"_2-提升用户体验","2. 提升用户体验",[256,284,285,291,297],{},[31,286,287,290],{},[34,288,289],{},"即开即用","：用户下载后直接运行，无需安装过程",[31,292,293,296],{},[34,294,295],{},"避免DLL地狱","：不会出现版本冲突或缺失DLL的问题",[31,298,299,302],{},[34,300,301],{},"便携性强","：可以将整个应用程序放在U盘中运行",[60,304,306],{"id":305},"_3-保护知识产权","3. 保护知识产权",[256,308,309,315],{},[31,310,311,314],{},[34,312,313],{},"代码混淆","：合并后的程序集更难被反编译",[31,316,317,320],{},[34,318,319],{},"依赖隐藏","：第三方库的实现细节被嵌入，增加逆向工程难度",[60,322,324],{"id":323},"_4-性能优化","4. 性能优化",[256,326,327,333],{},[31,328,329,332],{},[34,330,331],{},"减少I\u002FO操作","：所有程序集都在内存中，减少磁盘访问",[31,334,335,338],{},[34,336,337],{},"启动速度","：避免运行时查找和加载多个DLL文件的开销",[14,340,341],{"id":341},"应用场景",[60,343,345],{"id":344},"_1-wpf桌面应用程序","1. WPF桌面应用程序",[65,347,351],{"className":348,"code":349,"language":350,"meta":70,"style":70},"language-csharp shiki shiki-themes github-light github-dark","\u002F\u002F 典型的WPF应用场景\npublic partial class App : Application\n{\n    protected override void OnStartup(StartupEventArgs e)\n    {\n        \u002F\u002F 使用Costura.Fody后，所有依赖的DLL都会被自动加载\n        \u002F\u002F 包括Wpf.Ui、CommunityToolkit.Mvvm等\n        base.OnStartup(e);\n    }\n}\n","csharp",[72,352,353,358,363,368,373,378,383,388,393,398],{"__ignoreMap":70},[75,354,355],{"class":77,"line":78},[75,356,357],{},"\u002F\u002F 典型的WPF应用场景\n",[75,359,360],{"class":77,"line":84},[75,361,362],{},"public partial class App : Application\n",[75,364,365],{"class":77,"line":109},[75,366,367],{},"{\n",[75,369,370],{"class":77,"line":115},[75,371,372],{},"    protected override void OnStartup(StartupEventArgs e)\n",[75,374,375],{"class":77,"line":121},[75,376,377],{},"    {\n",[75,379,380],{"class":77,"line":127},[75,381,382],{},"        \u002F\u002F 使用Costura.Fody后，所有依赖的DLL都会被自动加载\n",[75,384,385],{"class":77,"line":133},[75,386,387],{},"        \u002F\u002F 包括Wpf.Ui、CommunityToolkit.Mvvm等\n",[75,389,390],{"class":77,"line":139},[75,391,392],{},"        base.OnStartup(e);\n",[75,394,395],{"class":77,"line":145},[75,396,397],{},"    }\n",[75,399,400],{"class":77,"line":151},[75,401,402],{},"}\n",[18,404,405,408],{},[34,406,407],{},"适用情况","：",[256,410,411,414,417],{},[31,412,413],{},"需要分发给最终用户的工具软件",[31,415,416],{},"企业内部使用的桌面应用",[31,418,419],{},"演示程序或原型应用",[60,421,423],{"id":422},"_2-控制台应用程序","2. 控制台应用程序",[65,425,427],{"className":348,"code":426,"language":350,"meta":70,"style":70},"class Program\n{\n    static void Main(string[] args)\n    {\n        \u002F\u002F 所有依赖的库都会被自动合并\n        var serviceProvider = new ServiceCollection()\n            .AddSingleton\u003CILogger, ConsoleLogger>()\n            .BuildServiceProvider();\n    }\n}\n",[72,428,429,434,438,443,447,452,457,462,467,471],{"__ignoreMap":70},[75,430,431],{"class":77,"line":78},[75,432,433],{},"class Program\n",[75,435,436],{"class":77,"line":84},[75,437,367],{},[75,439,440],{"class":77,"line":109},[75,441,442],{},"    static void Main(string[] args)\n",[75,444,445],{"class":77,"line":115},[75,446,377],{},[75,448,449],{"class":77,"line":121},[75,450,451],{},"        \u002F\u002F 所有依赖的库都会被自动合并\n",[75,453,454],{"class":77,"line":127},[75,455,456],{},"        var serviceProvider = new ServiceCollection()\n",[75,458,459],{"class":77,"line":133},[75,460,461],{},"            .AddSingleton\u003CILogger, ConsoleLogger>()\n",[75,463,464],{"class":77,"line":139},[75,465,466],{},"            .BuildServiceProvider();\n",[75,468,469],{"class":77,"line":145},[75,470,397],{},[75,472,473],{"class":77,"line":151},[75,474,402],{},[60,476,478],{"id":477},"_3-插件化应用程序","3. 插件化应用程序",[65,480,482],{"className":348,"code":481,"language":350,"meta":70,"style":70},"public class PluginManager\n{\n    public void LoadPlugins()\n    {\n        \u002F\u002F 主程序集合并后，插件加载逻辑保持不变\n        var pluginAssemblies = Directory.GetFiles(\"Plugins\", \"*.dll\");\n        foreach (var assembly in pluginAssemblies)\n        {\n            var pluginAssembly = Assembly.LoadFrom(assembly);\n            \u002F\u002F 加载插件逻辑...\n        }\n    }\n}\n",[72,483,484,489,493,498,502,507,512,517,522,527,532,537,541],{"__ignoreMap":70},[75,485,486],{"class":77,"line":78},[75,487,488],{},"public class PluginManager\n",[75,490,491],{"class":77,"line":84},[75,492,367],{},[75,494,495],{"class":77,"line":109},[75,496,497],{},"    public void LoadPlugins()\n",[75,499,500],{"class":77,"line":115},[75,501,377],{},[75,503,504],{"class":77,"line":121},[75,505,506],{},"        \u002F\u002F 主程序集合并后，插件加载逻辑保持不变\n",[75,508,509],{"class":77,"line":127},[75,510,511],{},"        var pluginAssemblies = Directory.GetFiles(\"Plugins\", \"*.dll\");\n",[75,513,514],{"class":77,"line":133},[75,515,516],{},"        foreach (var assembly in pluginAssemblies)\n",[75,518,519],{"class":77,"line":139},[75,520,521],{},"        {\n",[75,523,524],{"class":77,"line":145},[75,525,526],{},"            var pluginAssembly = Assembly.LoadFrom(assembly);\n",[75,528,529],{"class":77,"line":151},[75,530,531],{},"            \u002F\u002F 加载插件逻辑...\n",[75,533,534],{"class":77,"line":157},[75,535,536],{},"        }\n",[75,538,539],{"class":77,"line":163},[75,540,397],{},[75,542,543],{"class":77,"line":169},[75,544,402],{},[14,546,547],{"id":547},"注意事项和限制",[60,549,551],{"id":550},"_1-文件大小增加","1. 文件大小增加",[256,553,554,560],{},[31,555,556,557],{},"合并后的",[34,558,559],{},"exe文件会显著增大",[31,561,562],{},"需要考虑网络传输和存储成本",[60,564,566],{"id":565},"_2-调试复杂性","2. 调试复杂性",[256,568,569,572],{},[31,570,571],{},"调试时可能难以定位到具体的DLL问题",[31,573,574],{},"建议在开发阶段禁用合并功能",[60,576,578],{"id":577},"_3-版本更新","3. 版本更新",[256,580,581,584],{},[31,582,583],{},"任何依赖库的更新都需要重新编译整个应用程序",[31,585,586],{},"无法单独更新某个依赖项",[60,588,590],{"id":589},"_4-兼容性考虑","4. 兼容性考虑",[256,592,593,596],{},[31,594,595],{},"某些特殊的DLL可能不支持合并",[31,597,598],{},"需要测试所有功能确保正常工作",[14,600,601],{"id":601},"最佳实践",[60,603,605],{"id":604},"_1-选择性合并","1. 选择性合并",[65,607,609],{"className":67,"code":608,"language":69,"meta":70,"style":70},"\u003C!-- 只合并必要的依赖项 -->\n\u003CIncludeAssemblies>\n    \u003CInclude>Wpf.Ui\u003C\u002FInclude>\n    \u003CInclude>CommunityToolkit.Mvvm\u003C\u002FInclude>\n\u003C\u002FIncludeAssemblies>\n",[72,610,611,616,621,626,631],{"__ignoreMap":70},[75,612,613],{"class":77,"line":78},[75,614,615],{},"\u003C!-- 只合并必要的依赖项 -->\n",[75,617,618],{"class":77,"line":84},[75,619,620],{},"\u003CIncludeAssemblies>\n",[75,622,623],{"class":77,"line":109},[75,624,625],{},"    \u003CInclude>Wpf.Ui\u003C\u002FInclude>\n",[75,627,628],{"class":77,"line":115},[75,629,630],{},"    \u003CInclude>CommunityToolkit.Mvvm\u003C\u002FInclude>\n",[75,632,633],{"class":77,"line":121},[75,634,635],{},"\u003C\u002FIncludeAssemblies>\n",[60,637,639],{"id":638},"_2-开发与发布分离","2. 开发与发布分离",[65,641,643],{"className":67,"code":642,"language":69,"meta":70,"style":70},"\u003C!-- 开发环境配置 -->\n\u003CCreateTemporaryAssemblies Condition=\"'$(Configuration)' == 'Debug'\">true\u003C\u002FCreateTemporaryAssemblies>\n\u003CCreateTemporaryAssemblies Condition=\"'$(Configuration)' == 'Release'\">false\u003C\u002FCreateTemporaryAssemblies>\n",[72,644,645,650,655],{"__ignoreMap":70},[75,646,647],{"class":77,"line":78},[75,648,649],{},"\u003C!-- 开发环境配置 -->\n",[75,651,652],{"class":77,"line":84},[75,653,654],{},"\u003CCreateTemporaryAssemblies Condition=\"'$(Configuration)' == 'Debug'\">true\u003C\u002FCreateTemporaryAssemblies>\n",[75,656,657],{"class":77,"line":109},[75,658,659],{},"\u003CCreateTemporaryAssemblies Condition=\"'$(Configuration)' == 'Release'\">false\u003C\u002FCreateTemporaryAssemblies>\n",[60,661,663],{"id":662},"_3-性能监控","3. 性能监控",[256,665,666,669,672],{},[31,667,668],{},"监控合并后应用程序的启动时间",[31,670,671],{},"测试内存使用情况",[31,673,674],{},"确保所有功能正常工作",[14,676,677],{"id":677},"总结",[18,679,680],{},"​\tCostura.Fody是.NET应用程序实现单文件部署的优秀解决方案，特别适合需要简化部署流程的桌面应用程序。通过合理的配置和使用，可以显著提升应用程序的部署便利性和用户体验。然而，在使用时需要权衡文件大小、调试复杂性和维护成本等因素，选择最适合项目需求的合并策略。",[682,683,684],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":70,"searchDepth":84,"depth":84,"links":686},[687,688,689,693,699,704,710,715],{"id":16,"depth":84,"text":16},{"id":23,"depth":84,"text":23},{"id":58,"depth":84,"text":58,"children":690},[691,692],{"id":62,"depth":109,"text":63},{"id":90,"depth":109,"text":91},{"id":250,"depth":84,"text":250,"children":694},[695,696,697,698],{"id":253,"depth":109,"text":254},{"id":281,"depth":109,"text":282},{"id":305,"depth":109,"text":306},{"id":323,"depth":109,"text":324},{"id":341,"depth":84,"text":341,"children":700},[701,702,703],{"id":344,"depth":109,"text":345},{"id":422,"depth":109,"text":423},{"id":477,"depth":109,"text":478},{"id":547,"depth":84,"text":547,"children":705},[706,707,708,709],{"id":550,"depth":109,"text":551},{"id":565,"depth":109,"text":566},{"id":577,"depth":109,"text":578},{"id":589,"depth":109,"text":590},{"id":601,"depth":84,"text":601,"children":711},[712,713,714],{"id":604,"depth":109,"text":605},{"id":638,"depth":109,"text":639},{"id":662,"depth":109,"text":663},{"id":677,"depth":84,"text":677},"md",{},true,"\u002Fcsharp\u002Fwpf\u002F程序集合并dll",{"title":5,"description":70},"csharp\u002FWPF\u002F程序集合并dll","_L0MLmdUAHzY-nuacFyaXiQeQnmWKjV5W87sx6z_Mx4",1791042466470]