C# 如何正确地从元组继承,以便从奥尔良生成的序列化程序是正确的?

C# 如何正确地从元组继承,以便从奥尔良生成的序列化程序是正确的?,c#,tuples,.net-standard-2.0,orleans,.net-standard-2.1,C#,Tuples,.net Standard 2.0,Orleans,.net Standard 2.1,我有一个以netstandard2.0作为TargetFramework的项目,并有以下Nuget包: microsoft.orleans.core->Version=“2.2.0” microsoft.orleans.orleanscodegenerator.build->Version=“2.2.0” 此项目有一个DTO,它实现了如下元组: public sealed class SomeDetailsDto : Tuple<Guid, Guid> { p

我有一个以netstandard2.0作为TargetFramework的项目,并有以下Nuget包:

microsoft.orleans.core->Version=“2.2.0”
microsoft.orleans.orleanscodegenerator.build->Version=“2.2.0”

此项目有一个DTO,它实现了如下元组:

public sealed class SomeDetailsDto : Tuple<Guid, Guid>
    {
        public SomeDetailsDto(Guid firstGuidId, Guid secondGuidId)
            : base(firstGuidId, secondGuidId)
        {
        }

        public Guid firstGuidId => Item1;

        public Guid secondGuidId => Item2;
    }
最新的序列化程序忽略了警告中提到的元组的Item1和Item2。我在这个问题上搜索了很多,什么也没找到。我可以使用奥尔良文档中提到的自定义序列化程序。但我有另一个DTO,它也得到了前面提到的警告

解决此问题的更好方法是什么?

我建议不要从
元组继承。相反,将这些字段放在类上,使类看起来像这样:

[可序列化]
公共密封类SomeDetailsTo
{
public somedetailsdo(Guid firstGuidId,Guid secondGuidId)
{
FirstGuidId=FirstGuidId;
SecondGuidId=SecondGuidId;
}
公共Guid FirstGuidId{get;}
公共Guid{get;}
}
注意,我还向类添加了
[Serializable]
属性。我还建议您始终向要序列化的类型添加
[Serializable]
。代码生成器将尽最大努力推断您希望为该类型生成一个序列化程序(因为它出现在grain接口方法签名和其他启发式方法中),但该过程不能完全准确-因此最好是显式的

如果希望有一些公共类型指示类有2个字段(假设这对您有用),那么可以定义一个接口或自己的类元组类型,并在DTO上实现它

正如构建警告消息所指出的,
Tuple
是在一种称为ref-only程序集的特殊类型的程序集中定义的。这意味着奥尔良代码生成器无法查看
Tuple
类中的任何字段(那些仅引用的程序集省略了私有成员和所有IL代码,因此它们根本不存在)。如果不知道基类上存在哪些字段,代码生成器将无法为其生成正确的序列化程序。这是由ref only程序集造成的限制,奥尔良存储库中已经讨论了如何纠正此限制


这里有一个支持从
元组继承
和集合类型的功能请求:

如果奥尔良支持
ValueTuple
(int-firstGuidId,int-secondGuidId)
),则考虑改用
ValueTuple
),这样您就不必首先声明新类型<代码>元组
添加的内容不多。如果这不是一个选项,请考虑不要继承<代码> tuple < /C>和实现相等/散列(如果需要的话),例如支持。谢谢你的回答。让我感到不安的是NetStandard2.0没有这个问题。不知道目标框架会有什么不同。使用netstandard2.0与使用特定目标框架时,在构建时会选择不同的程序集。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(@"Orleans-CodeGenerator", @"2.0.0.0"), global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, global::Orleans.CodeGeneration.SerializerAttribute(typeof(global::SomeDetailsDto))]
    internal sealed class OrleansCodeGenSomeDetailsDtoSerializer
    {
        private readonly global::System.Func<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid> getField0;
        private readonly global::System.Action<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid> setField0;
        private readonly global::System.Func<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid> getField1;
        private readonly global::System.Action<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid> setField1;
        public OrleansCodeGenSomeDetailsDtoSerializer(global::Orleans.Serialization.IFieldUtils fieldUtils)
        {
            global::System.Reflection.FieldInfo field0 = typeof(global::System.Tuple<global::System.Guid, global::System.Guid>).GetField(@"m_Item1", (System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public));
            getField0 = (global::System.Func<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid>)fieldUtils.GetGetter(field0);
            setField0 = (global::System.Action<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid>)fieldUtils.GetReferenceSetter(field0);
            global::System.Reflection.FieldInfo field1 = typeof(global::System.Tuple<global::System.Guid, global::System.Guid>).GetField(@"m_Item2", (System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public));
            getField1 = (global::System.Func<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid>)fieldUtils.GetGetter(field1);
            setField1 = (global::System.Action<global::System.Tuple<global::System.Guid, global::System.Guid>, global::System.Guid>)fieldUtils.GetReferenceSetter(field1);
        }

        [global::Orleans.CodeGeneration.CopierMethodAttribute]
        public global::System.Object DeepCopier(global::System.Object original, global::Orleans.Serialization.ICopyContext context)
        {
            global::SomeDetailsDto input = ((global::SomeDetailsDto)original);
            global::SomeDetailsDto result = (global::SomeDetailsDto)global::System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(global::SomeDetailsDto));
            context.RecordCopy(original, result);
            setField0(result, getField0(input));
            setField1(result, getField1(input));
            return result;
        }

        [global::Orleans.CodeGeneration.SerializerMethodAttribute]
        public void Serializer(global::System.Object untypedInput, global::Orleans.Serialization.ISerializationContext context, global::System.Type expected)
        {
            global::SomeDetailsDto input = (global::SomeDetailsDto)untypedInput;
            context.SerializeInner(getField0(input), typeof(global::System.Guid));
            context.SerializeInner(getField1(input), typeof(global::System.Guid));
        }

        [global::Orleans.CodeGeneration.DeserializerMethodAttribute]
        public global::System.Object Deserializer(global::System.Type expected, global::Orleans.Serialization.IDeserializationContext context)
        {
            global::SomeDetailsDto result = (global::SomeDetailsDto)global::System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(global::SomeDetailsDto));
            context.RecordObject(result);
            setField0(result, (global::System.Guid)context.DeserializeInner(typeof(global::System.Guid)));
            setField1(result, (global::System.Guid)context.DeserializeInner(typeof(global::System.Guid)));
            return (global::SomeDetailsDto)result;
        }
    }

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("OrleansCodeGen", "2.0.0.0"), global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, global::Orleans.CodeGeneration.SerializerAttribute(typeof(global::SomeDetailsDto))]
    internal sealed class OrleansCodeGenSomeDetailsDtoSerializer
    {
        public OrleansCodeGenSomeDetailsDtoSerializer(global::Orleans.Serialization.IFieldUtils fieldUtils)
        {
        }

        [global::Orleans.CodeGeneration.CopierMethodAttribute]
        public object DeepCopier(object original, global::Orleans.Serialization.ICopyContext context)
        {
            global::SomeDetailsDto input = ((global::SomeDetailsDto)original);
            global::SomeDetailsDto result = (global::SomeDetailsDto)global::System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(global::SomeDetailsDto));
            context.RecordCopy(original, result);
            return result;
        }

        [global::Orleans.CodeGeneration.SerializerMethodAttribute]
        public void Serializer(object untypedInput, global::Orleans.Serialization.ISerializationContext context, global::System.Type expected)
        {
            global::SomeDetailsDto input = (global::SomeDetailsDto)untypedInput;
        }

        [global::Orleans.CodeGeneration.DeserializerMethodAttribute]
        public object Deserializer(global::System.Type expected, global::Orleans.Serialization.IDeserializationContext context)
        {
            global::SomeDetailsDto result = (global::SomeDetailsDto)global::System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(global::SomeDetailsDto));
            context.RecordObject(result);
            return (global::SomeDetailsDto)result;
        }
    }