C# 如何正确地从元组继承,以便从奥尔良生成的序列化程序是正确的?
我有一个以netstandard2.0作为TargetFramework的项目,并有以下Nuget包: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
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;
}
}