У меня есть проект с 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;
}
Этот DTO будет использоваться в зернистом методе. Сгенерированный orleans код сериализатора выглядит следующим образом:
[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;
}
}
Все это совершенно нормально.
Но недавно я обновил TargetFramework до netstandard2.1, microsoft.orleans.core до «3.0.2» и вместо microsoft.orleans.orleanscodegenerator.build (2.2.0) установил Microsoft. Орлеан.CodeGenerator.MSBuild (3.0.2).
С приведенной выше настройкой я получил следующее предупреждение:
предупреждение ORL1001: Тип SomeDetailsDto имеет базовый тип, принадлежащий эталонной сборке. Создание сериализатора для этого типа может не включать важные поля базового типа.
Команды Restore, Build и Publish работают. Однако сгенерированный сериализатор неисправен, из-за чего тесты не выполняются.
Ниже приведен сгенерированный orleans код для того же DTO.
[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;
}
}
Последний сериализатор проигнорировал Item1 и Item2 кортежа, как указано в предупреждении. Я много искал по этому вопросу и ничего не нашел. Я мог бы использовать собственный сериализатор, как указано в этой документации orleans. . Но у меня есть еще один DTO, который также получает ранее упомянутое предупреждение.
Что может быть лучшим способом решения этой проблемы?
ValueTuple
, если Orleans поддерживает его ((int firstGuidId, int secondGuidId)
), поэтому вам не нужно объявлять новый тип в первую очередь;Tuple
мало что добавляет. Если это невозможно, просто подумайте о том, чтобы не наследовать отTuple
и реализовать равенство/хеширование самостоятельно (где это необходимо), например, при поддержкеSystem.HashCode
. - person Jeroen Mostert   schedule 13.12.2019