Orleans 7.0默认序列化器无法处理NuGet包中的POCO类
Orleans 7.0 序列化器无法识别内部NuGet包模型的解决方案
问题重现
升级Orleans至7.0后,默认序列化器无法处理内部NuGet包中的模型与DTO,抛出CodecNotFoundException错误;但将模型类直接复制到主项目、或改用带IgnoreCycles的Json序列化器时,问题消失。即使直接引用模型项目(ProjectReference),错误依然存在。
错误日志示例:
Orleans.Serialization.CodecNotFoundException: Could not find a copier for type InternalProject.Model. at Orleans.Serialization.Serializers.CodecProvider.ThrowCopierNotFound(Type type) in /_/src/Orleans.Serialization/Serializers/CodecProvider.cs:line 666 ...(省略后续堆栈信息)
根本原因
Orleans 7.0默认使用源生成式序列化器,替代了旧版本的运行时序列化。若模型项目未正确配置代码生成、或NuGet包未包含生成的序列化代码,主项目无法识别模型的序列化器/复制器,从而抛出异常。
解决步骤
1. 配置模型项目启用序列化源生成
在生成NuGet包的模型类库项目(.csproj)中添加以下配置:
<PropertyGroup> <!-- 启用Orleans序列化代码生成 --> <OrleansSerializationCodeGeneration>true</OrleansSerializationCodeGeneration> </PropertyGroup> <ItemGroup> <!-- 引入序列化与代码生成包,设置PrivateAssets避免传递引用 --> <PackageReference Include="Orleans.Serialization" Version="7.0.*" PrivateAssets="all" /> <PackageReference Include="Orleans.CodeGenerator.MSBuild" Version="7.0.*" PrivateAssets="all" /> </ItemGroup>
2. 检查模型的序列化属性完整性
确保所有需要序列化的类型(包括基类、嵌套类、接口实现类)都正确标记:
- 类必须添加
[GenerateSerializer]特性 - 需序列化的属性必须添加
[Id(n)]特性(n为唯一整数ID,从0开始递增) - 接口
IRequest的具体实现类也必须标记[GenerateSerializer],Orleans无法直接序列化接口类型
示例正确标记的类:
[GenerateSerializer] public sealed class Class1 : Class1Base { public Class1() { } public Class1(IRequest request, bool flag, InternalClass internalClass) : base(request, flag) { InternalClass = internalClass; } [Id(0)] public InternalClass InternalClass { get; set; } } [GenerateSerializer] public class Class1Base { public Class1Base() { } public Class1Base(IRequest request, bool flag) { Request = request; BooleanFlag = flag; } [Id(0)] public IRequest Request { get; set; } [Id(1)] public bool BooleanFlag { get; set; } } // 嵌套类也需要正确标记 [GenerateSerializer] public class InternalClass { [Id(0)] public string Data { get; set; } } // IRequest的实现类必须标记 [GenerateSerializer] public class RequestImpl : IRequest { [Id(0)] public string Id { get; set; } }
3. 确保NuGet包包含源生成代码
在模型项目的.csproj中添加配置,将源生成的.orleans.g.cs文件打包进NuGet:
<ItemGroup> <!-- 将源生成的序列化代码包含到NuGet包中 --> <Compile Include="**/*.orleans.g.cs" Pack="true" PackagePath="lib/$(TargetFramework)" /> </ItemGroup>
4. 主项目显式注册模型程序集
在Silo或Client的配置代码中,注册模型所在的程序集,让Orleans扫描并加载序列化器:
// Silo配置示例 var siloBuilder = new SiloBuilder() .ConfigureServices(services => { services.AddOrleansSerialization(builder => { // 注册模型所在的程序集 builder.AddAssembly(typeof(Class1).Assembly); }); }) // 或通过ApplicationParts注册 .AddApplicationParts() .AddAssembly(typeof(Class1).Assembly);
5. 清理重建项目
- 删除所有项目的
bin、obj目录 - 清理NuGet缓存:执行
dotnet nuget locals all --clear - 重新生成模型项目并打包NuGet
- 主项目更新NuGet引用后重新编译
验证
完成以上步骤后,主项目引用NuGet包中的模型时,Orleans默认序列化器可正常生成复制器与序列化器,不再抛出CodecNotFoundException。
内容的提问来源于stack exchange,提问作者Professional_Amateur_Dev
相关产品推荐
相关产品推荐

