多项目引用不同版本parquet.net引发TypeLoadException的解决咨询
问题场景
我有一个包含A、X、Y三个项目的解决方案,其中A引用X和Y,X与Y分别引用不同版本的Parquet.Net(无法修改二者的Parquet.Net版本)。
A项目代码
var x = new X.Class1(); var y = new Y.Class1(); x.M(); Console.WriteLine(y.P);
X项目配置与代码
X项目文件(.csproj)
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Parquet.Net" Version="1.0.114" /> </ItemGroup> </Project>
X.Class1代码
using Parquet.Data; namespace X; public class Class1 { public void M() { Console.WriteLine(P); } }
Y项目配置与代码
Y的项目文件与X基本一致,仅Parquet.Net版本不同:
Y项目文件(.csproj)
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Parquet.Net" Version="4.20.0" /> </ItemGroup> </Project>
Y.Class1代码
using System.Data; namespace Y { public class Class1 { public DataSet? P { get; set; } } }
运行错误
运行程序时,在x.M()行抛出如下错误:
System.TypeLoadException HResult=0x80131522 Message=Could not load type 'Parquet.Data.DataSet' from assembly 'Parquet, Version=4.0.0.0, Culture=neutral, PublicKeyToken=d380b3dee6d01926'. Source=X StackTrace: at X.Class1.M() in C:\source\repos\ConsoleAppNet60\X\Class1.cs:line 12 at Program.<Main>$(String[] args) in C:\source\repos\ConsoleAppNet60\A\Program.cs:line 7
核心问题
能否在不修改X、Y的Parquet.Net版本且不使用Assembly Load Contexts的情况下解决该问题?
解决方案
可以解决,通过程序集绑定重定向+文件别名的方式实现,具体步骤如下:
在A项目的.csproj中添加依赖别名与文件重命名配置
为两个版本的Parquet.Net指定别名,并在编译后将程序集复制为不同文件名,避免冲突:<ItemGroup> <!-- 为X依赖的旧版本Parquet.Net指定别名 --> <PackageReference Include="Parquet.Net" Version="1.0.114" PrivateAssets="all"> <Aliases>ParquetV1</Aliases> </PackageReference> <!-- 为Y依赖的新版本Parquet.Net指定别名 --> <PackageReference Include="Parquet.Net" Version="4.20.0" PrivateAssets="all"> <Aliases>ParquetV4</Aliases> </PackageReference> </ItemGroup> <Target Name="CopyRenamedParquetAssemblies" AfterTargets="ResolveReferences"> <!-- 复制旧版本Parquet.dll为ParquetV1.dll --> <Copy SourceFiles="$(OutputPath)\Parquet.dll" DestinationFiles="$(OutputPath)\ParquetV1.dll" Condition="Exists('$(OutputPath)\Parquet.dll')" /> <!-- 复制新版本Parquet.dll为ParquetV4.dll --> <Copy SourceFiles="$(OutputPath)\Parquet.dll" DestinationFiles="$(OutputPath)\ParquetV4.dll" Condition="Exists('$(OutputPath)\Parquet.dll')" /> </Target> <!-- 启用自动生成绑定重定向(针对.NET Core/.NET 5+) --> <PropertyGroup> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> </PropertyGroup>添加程序集绑定重定向配置
在A项目的app.config(.NET Framework)或A.runtimeconfig.json(.NET Core/.NET 5+)中添加重定向规则,让X和Y分别加载对应版本的重命名程序集:<!-- app.config 内容 --> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!-- 让X加载旧版本的ParquetV1.dll --> <dependentAssembly> <assemblyIdentity name="Parquet" publicKeyToken="d380b3dee6d01926" culture="neutral" /> <bindingRedirect oldVersion="1.0.114.0" newVersion="1.0.114.0" /> <codeBase version="1.0.114.0" href="ParquetV1.dll" /> </dependentAssembly> <!-- 让Y加载新版本的ParquetV4.dll --> <dependentAssembly> <assemblyIdentity name="Parquet" publicKeyToken="d380b3dee6d01926" culture="neutral" /> <bindingRedirect oldVersion="4.20.0.0" newVersion="4.20.0.0" /> <codeBase version="4.20.0.0" href="ParquetV4.dll" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>验证生效
编译运行后,X项目会加载ParquetV1.dll(旧版本),Y项目会加载ParquetV4.dll(新版本),类型加载冲突即可解决。
内容的提问来源于stack exchange,提问作者ca9163d9
相关产品推荐
相关产品推荐

