Orleans 7.0 序列化程序无法与源自 Nuget 包的 POCO 一起使用

Pro*_*Dev 4 c# orleans .net-7.0

我有一个 Orleans 7.0 项目,并且我遇到了新的默认序列化器的问题。

\n

Orleans 3.6.5 中的旧序列化程序运行良好,它可以序列化几个内部 Nuget 包中的所有模型和 Dtos。

\n

现在在 Orleans 7.0 中,该项目无法识别 Nuget 包中的模型,并且出现以下错误:

\n
Orleans.Serialization.CodecNotFoundException: Could not find a copier for type InternalProject.Model.\n\xc2\xa0\xc2\xa0 at Orleans.Serialization.Serializers.CodecProvider.ThrowCopierNotFound(Type type) in /_/src/Orleans.Serialization/Serializers/CodecProvider.cs:line 666\n\xc2\xa0\xc2\xa0 at Orleans.Serialization.Serializers.CodecProvider.GetDeepCopier[T]() in /_/src/Orleans.Serialization/Serializers/CodecProvider.cs:line 300\n\xc2\xa0\xc2\xa0 at Orleans.Serialization.ServiceCollectionExtensions.CopierHolder`1.get_Value() in /_/src/Orleans.Serialization/Hosting/ServiceCollectionExtensions.cs:line 203\n\xc2\xa0\xc2\xa0 at Orleans.Serialization.GeneratedCodeHelpers.OrleansGeneratedCodeHelper.GetService[TService](Object caller, ICodecProvider codecProvider) in /_/src/Orleans.Serialization/GeneratedCodeHelpers/OrleansGeneratedCodeHelper.cs:lin\ne 75\n\xc2\xa0\xc2\xa0 at OrleansCodeGen.InternalProject.Model.Copier_SpecificModel..ctor(ICodecProvider codecProvider) in C:\\Projects\\InternalProject.Model\\Orleans.CodeGenerator\\Orleans.CodeGenerator.Orle\nansSerializationSourceGenerator\\InternalProject.Model.orleans.g.cs:line 20736\n\xc2\xa0\xc2\xa0 at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)\n\xc2\xa0\xc2\xa0 at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)\n\xc2\xa0\xc2\xa0 at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\n\xc2\xa0\xc2\xa0 at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)\n\xc2\xa0\xc2\xa0 at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)\n\xc2\xa0\xc2\xa0 at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance[T](IServiceProvider provider)\n\xc2\xa0\xc2\xa0 at Orleans.Serialization.GeneratedCodeHelpers.OrleansGeneratedCodeHelper.GetService[TService](Object caller, ICodecProvider codecProvider) in /_/src/Orleans.Serialization/GeneratedCodeHelpers/OrleansGeneratedCodeHelper.cs:lin\ne 72\n
Run Code Online (Sandbox Code Playgroud)\n

现在有趣的部分是:当我在主项目中复制粘贴完全相同的类时,我不再收到此错误,并且该类序列化得很好。

\n

我尝试在主项目(ProjectReference)中直接引用Nuget项目,结果是一样的。

\n

我只在两种情况下消除错误:

\n
    \n
  1. 当我将 Json Serializer 与 IgnoreCycles 一起使用时(在我的场景中是不可取的,并不能消除根本问题)
  2. \n
\n
siloBuilder.Services.AddSerializer(sb =>\n                    {\n                        sb.AddJsonSerializer(\n                            isSupported: type => type.Namespace.StartsWith("Nuget.Namespace"),\n                            new JsonSerializerOptions()\n                            {\n                                ReferenceHandler = ReferenceHandler.IgnoreCycles\n                            }\n                        );\n                    });\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 当我直接在主项目中添加类时。错误中的示例类:
  2. \n
\n
[GenerateSerializer]\n    public sealed class Class1: Class1Base\n    {\n        public Class1()\n        {\n            \n        }\n\n        public Class1(IRequest request, bool boolean, InternalClass internalClass) \n            : base(request, boolean)\n        {\n            InternalClass = internalClass;\n        }\n\n        [Id(0)]\n        public InternalClass InternalClass{ get; set; }\n        \n    }\n\n   [GenerateSerializer]\n    public class Class1Base\n    {\n        public Class1Base()\n        {\n            \n        }\n        public Class1Base(IRequest request, bool boolean)\n        {\n            Request = request;\n            Boolean= boolean;\n        }\n\n        [Id(0)]\n        public IRequest Request { get; set; }\n        [Id(1)]\n        public bool Boolean{ get; set; }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

小智 5

Orleans 序列化器具有很多性能和灵活性优势,但正如您所发现的,它在使用第 3 方类型方面具有非常硬的优势。你有几个选择,但都不是很好

  1. 继续使用第 3 方类型并为您将序列化的每种类型定义代理和编解码器。这可能是一项非常繁重的工作,而且可能不是最好的主意。请参阅此文档了解如何执行此操作,但请注意,如果您不小心错过了图中的类型,它会在运行时崩溃,因此请确保您的测试良好。

  2. 使用不同的序列化器。Orleans 附带了基于 Json 的序列化器,更容易使用。它们可能不如 Orleans Serializer 快,但运行起来要简单得多。这是最简单的选择,而且几乎没有什么缺点。请参阅这篇文章了解如何执行此操作

  3. 从 DTO 中删除第 3 方类型。在此选项中,您可以更改grain合约,以便仅使用第一方类型(您自己定义的类型)在grain之间发送消息。这不太方便,并且消除了奥尔良对象透明度的一些魔力,但消除了问题。这是我在我的案例中选择的选项,因为我认为它可以使我的模型保持干净。

我还怀疑,通过大量的努力,可能可以编写一个源生成器,它可以自动遍历grain调用中使用的对象图,并自动生成第三方类型的编解码器和代理,以完全消除这个问题。但我觉得没有必要。