.NET 6.0 依赖项输出到子目录及相关技术问题
1. 相对路径的有效配置
在.deps.json中使用相对路径时,需基于应用程序的工作目录,或使用官方提供的$assemblybasepath$占位符(运行时会自动替换为程序集所在的实际目录)。示例配置:
"ClassLibrary3/1.0.0": { "runtime": { "$assemblybasepath$/lib/ClassLibrary3.dll": {} } }
同时,在runtimeconfig.template.json或通过MSBuild配置的additionalProbingPaths中,相对路径是相对于应用根目录的,比如:
{ "runtimeOptions": { "additionalProbingPaths": ["lib"] } }
2. 构建前完成路径配置(无需手动修改.deps.json)
方案一:通过MSBuild属性控制项目引用输出
在主项目的.csproj中配置ProjectReference时,指定复制到子目录的规则,构建时自动生成正确的依赖路径:
<ProjectReference Include="..\ClassLibrary3\ClassLibrary3.csproj"> <Private>true</Private> <!-- 确保引用项目的输出复制到主项目的lib子目录 --> <CopyToOutputSubDirectory>lib</CopyToOutputSubDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </ProjectReference>
方案二:自动生成runtimeconfig探测路径
无需手动维护runtimeconfig.template.json,直接在主项目.csproj中添加MSBuild配置,自动将子目录加入探测路径:
<ItemGroup> <RuntimeHostConfigurationOption Include="additionalProbingPaths" Value="lib" /> </ItemGroup>
方案三:自定义MSBuild目标修改.deps.json
如果需要更复杂的路径控制,可添加自定义MSBuild目标,在构建后自动修改.deps.json的路径,示例:
<Target Name="ModifyDepsJson" AfterTargets="Build"> <XmlPoke XmlInputPath="$(OutputPath)$(AssemblyName).deps.json" Query="/*/runtime/ClassLibrary3/1.0.0/runtime/*/@key" Value="$assemblybasepath$/lib/ClassLibrary3.dll" /> </Target>
3. 更优处理方案
方案一:直接控制引用项目的输出路径
在引用项目的.csproj中设置OutputPath,让编译后的DLL直接输出到主项目的指定子目录,主项目会自动识别依赖:
<OutputPath>$(SolutionDir)MainProject\bin\$(Configuration)\net6.0\lib</OutputPath>
方案二:使用本地NuGet源管理依赖
将不同版本的类库打包为NuGet包,发布到本地NuGet源,主项目通过NuGet引用不同版本。NuGet会自动处理版本隔离,将不同版本的DLL放置到独立目录,无需手动配置路径。
方案三:自定义AssemblyLoadContext(灵活度最高)
通过自定义AssemblyLoadContext,手动从指定子目录加载DLL,完全控制加载逻辑,适合复杂的依赖隔离场景。
4. 同一DLL不同版本的处理
方案一:NuGet版本隔离
将不同版本的DLL打包为不同版本的NuGet包,主项目直接引用对应版本。.NET运行时会根据依赖解析规则,自动加载对应版本的DLL,NuGet会将不同版本的文件隔离存放。
方案二:自定义AssemblyLoadContext隔离版本
创建独立的加载上下文,分别加载不同版本的DLL,避免版本冲突:
// 加载v1版本 var alcV1 = new AssemblyLoadContext("ClassLibrary3_V1", isCollectible: true); var pathV1 = Path.Combine(AppContext.BaseDirectory, "lib", "v1", "ClassLibrary3.dll"); var assemblyV1 = alcV1.LoadFromAssemblyPath(pathV1); // 加载v2版本 var alcV2 = new AssemblyLoadContext("ClassLibrary3_V2", isCollectible: true); var pathV2 = Path.Combine(AppContext.BaseDirectory, "lib", "v2", "ClassLibrary3.dll"); var assemblyV2 = alcV2.LoadFromAssemblyPath(pathV2);
方案三:绑定重定向(兼容旧模式)
在.runtimeconfig.json中配置绑定重定向,指定旧版本替换为新版本:
{ "runtimeOptions": { "configProperties": { "Microsoft.NETCore.DotNetHostPolicy.Setup": { "bindingRedirects": [ { "name": "ClassLibrary3", "oldVersion": "1.0.0.0-1.9.9.9", "newVersion": "2.0.0.0" } ] } } } }
内容的提问来源于stack exchange,提问作者Itay G

