Merge pull request #1093 from AArnott/develop
Merge master into develop
This commit is contained in:
Коммит
5a6cda6f9f
|
@ -2429,6 +2429,112 @@ namespace MessagePack.Formatters.SharedData
|
|||
}
|
||||
}
|
||||
|
||||
public sealed class GenericConstrainedClassIntKeyFormatter<T1, T2> : global::MessagePack.Formatters.IMessagePackFormatter<global::SharedData.GenericConstrainedClassIntKey<T1, T2>>
|
||||
where T1 : class
|
||||
where T2 : class, global::System.Collections.Generic.IEqualityComparer<T1>
|
||||
{
|
||||
|
||||
public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::SharedData.GenericConstrainedClassIntKey<T1, T2> value, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNil();
|
||||
return;
|
||||
}
|
||||
|
||||
global::MessagePack.IFormatterResolver formatterResolver = options.Resolver;
|
||||
writer.WriteArrayHeader(2);
|
||||
formatterResolver.GetFormatterWithVerify<T1>().Serialize(ref writer, value.MyProperty0, options);
|
||||
formatterResolver.GetFormatterWithVerify<T2>().Serialize(ref writer, value.Comparer, options);
|
||||
}
|
||||
|
||||
public global::SharedData.GenericConstrainedClassIntKey<T1, T2> Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
options.Security.DepthStep(ref reader);
|
||||
global::MessagePack.IFormatterResolver formatterResolver = options.Resolver;
|
||||
var length = reader.ReadArrayHeader();
|
||||
var __MyProperty0__ = default(T1);
|
||||
var __Comparer__ = default(T2);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
__MyProperty0__ = formatterResolver.GetFormatterWithVerify<T1>().Deserialize(ref reader, options);
|
||||
break;
|
||||
case 1:
|
||||
__Comparer__ = formatterResolver.GetFormatterWithVerify<T2>().Deserialize(ref reader, options);
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var ____result = new global::SharedData.GenericConstrainedClassIntKey<T1, T2>();
|
||||
____result.MyProperty0 = __MyProperty0__;
|
||||
____result.Comparer = __Comparer__;
|
||||
reader.Depth--;
|
||||
return ____result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GenericConstrainedStructIntKeyFormatter<T1, T2> : global::MessagePack.Formatters.IMessagePackFormatter<global::SharedData.GenericConstrainedStructIntKey<T1, T2>>
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged, global::System.Collections.Generic.IEqualityComparer<T1>
|
||||
{
|
||||
|
||||
public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::SharedData.GenericConstrainedStructIntKey<T1, T2> value, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
global::MessagePack.IFormatterResolver formatterResolver = options.Resolver;
|
||||
writer.WriteArrayHeader(2);
|
||||
formatterResolver.GetFormatterWithVerify<T1>().Serialize(ref writer, value.MyProperty0, options);
|
||||
formatterResolver.GetFormatterWithVerify<T2>().Serialize(ref writer, value.Comparer, options);
|
||||
}
|
||||
|
||||
public global::SharedData.GenericConstrainedStructIntKey<T1, T2> Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
throw new global::System.InvalidOperationException("typecode is null, struct not supported");
|
||||
}
|
||||
|
||||
options.Security.DepthStep(ref reader);
|
||||
global::MessagePack.IFormatterResolver formatterResolver = options.Resolver;
|
||||
var length = reader.ReadArrayHeader();
|
||||
var __MyProperty0__ = default(T1);
|
||||
var __Comparer__ = default(T2);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
__MyProperty0__ = formatterResolver.GetFormatterWithVerify<T1>().Deserialize(ref reader, options);
|
||||
break;
|
||||
case 1:
|
||||
__Comparer__ = formatterResolver.GetFormatterWithVerify<T2>().Deserialize(ref reader, options);
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var ____result = new global::SharedData.GenericConstrainedStructIntKey<T1, T2>();
|
||||
____result.MyProperty0 = __MyProperty0__;
|
||||
____result.Comparer = __Comparer__;
|
||||
reader.Depth--;
|
||||
return ____result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GenericStructFormatter<T1, T2> : global::MessagePack.Formatters.IMessagePackFormatter<global::SharedData.GenericStruct<T1, T2>>
|
||||
{
|
||||
|
||||
|
@ -3927,6 +4033,144 @@ namespace MessagePack.Formatters.SharedData
|
|||
}
|
||||
}
|
||||
|
||||
public sealed class GenericConstrainedClassStringKeyFormatter<T1, T2> : global::MessagePack.Formatters.IMessagePackFormatter<global::SharedData.GenericConstrainedClassStringKey<T1, T2>>
|
||||
where T1 : class
|
||||
where T2 : class, global::System.Collections.Generic.IEqualityComparer<T1>
|
||||
{
|
||||
// MyProperty0
|
||||
private static global::System.ReadOnlySpan<byte> GetSpan_MyProperty0() => new byte[1 + 11] { 171, 77, 121, 80, 114, 111, 112, 101, 114, 116, 121, 48 };
|
||||
// Comparer
|
||||
private static global::System.ReadOnlySpan<byte> GetSpan_Comparer() => new byte[1 + 8] { 168, 67, 111, 109, 112, 97, 114, 101, 114 };
|
||||
|
||||
public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::SharedData.GenericConstrainedClassStringKey<T1, T2> value, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
writer.WriteNil();
|
||||
return;
|
||||
}
|
||||
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
writer.WriteMapHeader(2);
|
||||
writer.WriteRaw(GetSpan_MyProperty0());
|
||||
formatterResolver.GetFormatterWithVerify<T1>().Serialize(ref writer, value.MyProperty0, options);
|
||||
writer.WriteRaw(GetSpan_Comparer());
|
||||
formatterResolver.GetFormatterWithVerify<T2>().Serialize(ref writer, value.Comparer, options);
|
||||
}
|
||||
|
||||
public global::SharedData.GenericConstrainedClassStringKey<T1, T2> Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
options.Security.DepthStep(ref reader);
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
var length = reader.ReadMapHeader();
|
||||
var __MyProperty0__ = default(T1);
|
||||
var __Comparer__ = default(T2);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
ReadOnlySpan<byte> stringKey = global::MessagePack.Internal.CodeGenHelpers.ReadStringSpan(ref reader);
|
||||
switch (stringKey.Length)
|
||||
{
|
||||
default:
|
||||
FAIL:
|
||||
reader.Skip();
|
||||
continue;
|
||||
case 11:
|
||||
if (!global::System.MemoryExtensions.SequenceEqual(stringKey, GetSpan_MyProperty0().Slice(1))) { goto FAIL; }
|
||||
|
||||
__MyProperty0__ = formatterResolver.GetFormatterWithVerify<T1>().Deserialize(ref reader, options);
|
||||
continue;
|
||||
case 8:
|
||||
if (global::MessagePack.Internal.AutomataKeyGen.GetKey(ref stringKey) != 8243120455795175235UL) { goto FAIL; }
|
||||
|
||||
__Comparer__ = formatterResolver.GetFormatterWithVerify<T2>().Deserialize(ref reader, options);
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var ____result = new global::SharedData.GenericConstrainedClassStringKey<T1, T2>()
|
||||
{
|
||||
MyProperty0 = __MyProperty0__,
|
||||
Comparer = __Comparer__,
|
||||
};
|
||||
|
||||
reader.Depth--;
|
||||
return ____result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GenericConstrainedStructStringKeyFormatter<T1, T2> : global::MessagePack.Formatters.IMessagePackFormatter<global::SharedData.GenericConstrainedStructStringKey<T1, T2>>
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged, global::System.Collections.Generic.IEqualityComparer<T1>
|
||||
{
|
||||
// MyProperty0
|
||||
private static global::System.ReadOnlySpan<byte> GetSpan_MyProperty0() => new byte[1 + 11] { 171, 77, 121, 80, 114, 111, 112, 101, 114, 116, 121, 48 };
|
||||
// Comparer
|
||||
private static global::System.ReadOnlySpan<byte> GetSpan_Comparer() => new byte[1 + 8] { 168, 67, 111, 109, 112, 97, 114, 101, 114 };
|
||||
|
||||
public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::SharedData.GenericConstrainedStructStringKey<T1, T2> value, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
writer.WriteMapHeader(2);
|
||||
writer.WriteRaw(GetSpan_MyProperty0());
|
||||
formatterResolver.GetFormatterWithVerify<T1>().Serialize(ref writer, value.MyProperty0, options);
|
||||
writer.WriteRaw(GetSpan_Comparer());
|
||||
formatterResolver.GetFormatterWithVerify<T2>().Serialize(ref writer, value.Comparer, options);
|
||||
}
|
||||
|
||||
public global::SharedData.GenericConstrainedStructStringKey<T1, T2> Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
throw new global::System.InvalidOperationException("typecode is null, struct not supported");
|
||||
}
|
||||
|
||||
options.Security.DepthStep(ref reader);
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
var length = reader.ReadMapHeader();
|
||||
var __MyProperty0__ = default(T1);
|
||||
var __Comparer__ = default(T2);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
ReadOnlySpan<byte> stringKey = global::MessagePack.Internal.CodeGenHelpers.ReadStringSpan(ref reader);
|
||||
switch (stringKey.Length)
|
||||
{
|
||||
default:
|
||||
FAIL:
|
||||
reader.Skip();
|
||||
continue;
|
||||
case 11:
|
||||
if (!global::System.MemoryExtensions.SequenceEqual(stringKey, GetSpan_MyProperty0().Slice(1))) { goto FAIL; }
|
||||
|
||||
__MyProperty0__ = formatterResolver.GetFormatterWithVerify<T1>().Deserialize(ref reader, options);
|
||||
continue;
|
||||
case 8:
|
||||
if (global::MessagePack.Internal.AutomataKeyGen.GetKey(ref stringKey) != 8243120455795175235UL) { goto FAIL; }
|
||||
|
||||
__Comparer__ = formatterResolver.GetFormatterWithVerify<T2>().Deserialize(ref reader, options);
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var ____result = new global::SharedData.GenericConstrainedStructStringKey<T1, T2>()
|
||||
{
|
||||
MyProperty0 = __MyProperty0__,
|
||||
Comparer = __Comparer__,
|
||||
};
|
||||
|
||||
reader.Depth--;
|
||||
return ____result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class NonEmpty2Formatter : global::MessagePack.Formatters.IMessagePackFormatter<global::SharedData.NonEmpty2>
|
||||
{
|
||||
// MyProperty
|
||||
|
|
|
@ -56,14 +56,22 @@ foreach (var objInfo in ObjectSerializationInfos)
|
|||
list.Add(new ValueTuple<MemberSerializationInfo, byte[]>(member, binary));
|
||||
}
|
||||
|
||||
string formatterName = objInfo.Name + (objInfo.IsOpenGenericType ? $"Formatter<{string.Join(",", (object[])objInfo.GenericTypeParameters)}>" : "Formatter");
|
||||
string formatterName = objInfo.Name + (objInfo.IsOpenGenericType ? $"Formatter<{string.Join(", ", objInfo.GenericTypeParameters.Select(x => x.Name))}>" : "Formatter");
|
||||
bool isFormatterResolverNecessary = ShouldUseFormatterResolverHelper.ShouldUseFormatterResolver(objInfo.Members);
|
||||
|
||||
this.Write("\r\n public sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(formatterName));
|
||||
this.Write(" : global::MessagePack.Formatters.IMessagePackFormatter<");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(objInfo.FullName));
|
||||
this.Write(">\r\n {\r\n");
|
||||
this.Write(">\r\n");
|
||||
foreach (var typeArg in objInfo.GenericTypeParameters.Where(x => x.HasConstraints)) {
|
||||
this.Write(" where ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(typeArg.Name));
|
||||
this.Write(" : ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(typeArg.Constraints));
|
||||
this.Write("\r\n");
|
||||
}
|
||||
this.Write(" {\r\n");
|
||||
|
||||
foreach (var memberAndBinary in list)
|
||||
{
|
||||
|
|
|
@ -37,11 +37,14 @@ foreach (var objInfo in ObjectSerializationInfos)
|
|||
list.Add(new ValueTuple<MemberSerializationInfo, byte[]>(member, binary));
|
||||
}
|
||||
|
||||
string formatterName = objInfo.Name + (objInfo.IsOpenGenericType ? $"Formatter<{string.Join(",", (object[])objInfo.GenericTypeParameters)}>" : "Formatter");
|
||||
string formatterName = objInfo.Name + (objInfo.IsOpenGenericType ? $"Formatter<{string.Join(", ", objInfo.GenericTypeParameters.Select(x => x.Name))}>" : "Formatter");
|
||||
bool isFormatterResolverNecessary = ShouldUseFormatterResolverHelper.ShouldUseFormatterResolver(objInfo.Members);
|
||||
#>
|
||||
|
||||
public sealed class <#= formatterName #> : global::MessagePack.Formatters.IMessagePackFormatter<<#= objInfo.FullName #>>
|
||||
<# foreach (var typeArg in objInfo.GenericTypeParameters.Where(x => x.HasConstraints)) {#>
|
||||
where <#= typeArg.Name #> : <#= typeArg.Constraints #>
|
||||
<# }#>
|
||||
{
|
||||
<#
|
||||
foreach (var memberAndBinary in list)
|
||||
|
|
|
@ -1617,8 +1617,14 @@ namespace MessagePack.Internal
|
|||
if (isIntKey)
|
||||
{
|
||||
member.IntKey = key.IntKey.Value;
|
||||
if (intMembers.ContainsKey(member.IntKey))
|
||||
if (intMembers.TryGetValue(member.IntKey, out EmittableMember conflictingMember))
|
||||
{
|
||||
// Quietly skip duplicate if this is an override property.
|
||||
if ((conflictingMember.PropertyInfo.SetMethod?.IsVirtual ?? false) || (conflictingMember.PropertyInfo.GetMethod?.IsVirtual ?? false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new MessagePackDynamicObjectResolverException("key is duplicated, all members key must be unique." + " type: " + type.FullName + " member:" + item.Name);
|
||||
}
|
||||
|
||||
|
@ -1627,8 +1633,14 @@ namespace MessagePack.Internal
|
|||
else
|
||||
{
|
||||
member.StringKey = key.StringKey;
|
||||
if (stringMembers.ContainsKey(member.StringKey))
|
||||
if (stringMembers.TryGetValue(member.StringKey, out EmittableMember conflictingMember))
|
||||
{
|
||||
// Quietly skip duplicate if this is an override property.
|
||||
if ((conflictingMember.PropertyInfo.SetMethod?.IsVirtual ?? false) || (conflictingMember.PropertyInfo.GetMethod?.IsVirtual ?? false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new MessagePackDynamicObjectResolverException("key is duplicated, all members key must be unique." + " type: " + type.FullName + " member:" + item.Name);
|
||||
}
|
||||
|
||||
|
|
|
@ -467,6 +467,50 @@ namespace SharedData
|
|||
public T2 MyProperty1 { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class GenericConstrainedClassIntKey<T1, T2>
|
||||
where T1 : class
|
||||
where T2 : class, IEqualityComparer<T1>
|
||||
{
|
||||
[Key(0)]
|
||||
public T1 MyProperty0 { get; set; }
|
||||
|
||||
[Key(1)]
|
||||
public T2 Comparer { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public class GenericConstrainedClassStringKey<T1, T2>
|
||||
where T1 : class
|
||||
where T2 : class, IEqualityComparer<T1>
|
||||
{
|
||||
public T1 MyProperty0 { get; set; }
|
||||
|
||||
public T2 Comparer { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public struct GenericConstrainedStructIntKey<T1, T2>
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged, IEqualityComparer<T1>
|
||||
{
|
||||
[Key(0)]
|
||||
public T1 MyProperty0 { get; set; }
|
||||
|
||||
[Key(1)]
|
||||
public T2 Comparer { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public struct GenericConstrainedStructStringKey<T1, T2>
|
||||
where T1 : unmanaged
|
||||
where T2 : unmanaged, IEqualityComparer<T1>
|
||||
{
|
||||
public T1 MyProperty0 { get; set; }
|
||||
|
||||
public T2 Comparer { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class VersionBlockTest
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using MessagePack.Resolvers;
|
||||
using Nerdbank.Streams;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
@ -45,6 +46,95 @@ namespace MessagePack.Tests
|
|||
PrivateMembersInBaseClass_Helper(options);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeserializerSetsMissingPropertiesToDefaultValue()
|
||||
{
|
||||
var seq = new Sequence<byte>();
|
||||
var writer = new MessagePackWriter(seq);
|
||||
writer.WriteMapHeader(1);
|
||||
writer.Write(nameof(TwoProperties.Prop1));
|
||||
writer.Write("Set");
|
||||
writer.Flush();
|
||||
|
||||
var instance = MessagePackSerializer.Deserialize<TwoProperties>(seq);
|
||||
Assert.Equal("Set", instance.Prop1);
|
||||
Assert.Null(instance.Prop2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeserializerSetsMissingPropertiesToDefaultValue_OrdinalKey()
|
||||
{
|
||||
var seq = new Sequence<byte>();
|
||||
var writer = new MessagePackWriter(seq);
|
||||
writer.WriteArrayHeader(1);
|
||||
writer.Write("Set");
|
||||
writer.Flush();
|
||||
|
||||
var instance = MessagePackSerializer.Deserialize<TwoPropertiesOrdinalKey>(seq);
|
||||
Assert.Equal("Set", instance.Prop1);
|
||||
Assert.Null(instance.Prop2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that virtual and overridden properties do not cause the dynamic resolver to malfunction.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VirtualOverriddenProperties()
|
||||
{
|
||||
var obj = new DerivedClassThatOverridesProperty { VirtualProperty = 100 };
|
||||
byte[] bin = MessagePackSerializer.Serialize(obj);
|
||||
var obj2 = MessagePackSerializer.Deserialize<DerivedClassThatOverridesProperty>(bin);
|
||||
Assert.Equal(obj.VirtualProperty, obj2.VirtualProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VirtualOverriddenProperties_DataMemberOnBase()
|
||||
{
|
||||
var obj = new DerivedClassThatOverridesPropertyDataMemberOnVirtualOnly { VirtualProperty = 100 };
|
||||
byte[] bin = MessagePackSerializer.Serialize(obj);
|
||||
var obj2 = MessagePackSerializer.Deserialize<DerivedClassThatOverridesPropertyDataMemberOnVirtualOnly>(bin);
|
||||
Assert.Equal(obj.VirtualProperty, obj2.VirtualProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VirtualOverriddenProperties_DataMemberOnOverride()
|
||||
{
|
||||
var obj = new DerivedClassThatOverridesPropertyDataMemberOnOverrideOnly { VirtualProperty = 100 };
|
||||
byte[] bin = MessagePackSerializer.Serialize(obj);
|
||||
var obj2 = MessagePackSerializer.Deserialize<DerivedClassThatOverridesPropertyDataMemberOnOverrideOnly>(bin);
|
||||
Assert.Equal(obj.VirtualProperty, obj2.VirtualProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that virtual and overridden properties do not cause the dynamic resolver to malfunction.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VirtualOverriddenProperties_OrdinalKey()
|
||||
{
|
||||
var obj = new DerivedClassThatOverridesPropertyOrdinalKey { VirtualProperty = 100 };
|
||||
byte[] bin = MessagePackSerializer.Serialize(obj);
|
||||
var obj2 = MessagePackSerializer.Deserialize<DerivedClassThatOverridesPropertyOrdinalKey>(bin);
|
||||
Assert.Equal(obj.VirtualProperty, obj2.VirtualProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VirtualOverriddenProperties_DataMemberOnBase_OrdinalKey()
|
||||
{
|
||||
var obj = new DerivedClassThatOverridesPropertyDataMemberOnVirtualOnlyOrdinalKey { VirtualProperty = 100 };
|
||||
byte[] bin = MessagePackSerializer.Serialize(obj);
|
||||
var obj2 = MessagePackSerializer.Deserialize<DerivedClassThatOverridesPropertyDataMemberOnVirtualOnlyOrdinalKey>(bin);
|
||||
Assert.Equal(obj.VirtualProperty, obj2.VirtualProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VirtualOverriddenProperties_DataMemberOnOverride_OrdinalKey()
|
||||
{
|
||||
var obj = new DerivedClassThatOverridesPropertyDataMemberOnOverrideOnlyOrdinalKey { VirtualProperty = 100 };
|
||||
byte[] bin = MessagePackSerializer.Serialize(obj);
|
||||
var obj2 = MessagePackSerializer.Deserialize<DerivedClassThatOverridesPropertyDataMemberOnOverrideOnlyOrdinalKey>(bin);
|
||||
Assert.Equal(obj.VirtualProperty, obj2.VirtualProperty);
|
||||
}
|
||||
|
||||
private static void Assert3MemberClassSerializedContent(ReadOnlyMemory<byte> msgpack)
|
||||
{
|
||||
var reader = new MessagePackReader(msgpack);
|
||||
|
@ -65,6 +155,130 @@ namespace MessagePack.Tests
|
|||
Assert.Equal(obj.Name, obj2.Name);
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseClassWithVirtualProperty
|
||||
{
|
||||
[DataMember]
|
||||
public virtual int VirtualProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class DerivedClassThatOverridesProperty : BaseClassWithVirtualProperty
|
||||
{
|
||||
[DataMember]
|
||||
public override int VirtualProperty
|
||||
{
|
||||
get => base.VirtualProperty;
|
||||
set => base.VirtualProperty = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseClassWithVirtualPropertyDataMemberOnOverrideOnly
|
||||
{
|
||||
public virtual int VirtualProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class DerivedClassThatOverridesPropertyDataMemberOnOverrideOnly : BaseClassWithVirtualPropertyDataMemberOnOverrideOnly
|
||||
{
|
||||
[DataMember]
|
||||
public override int VirtualProperty
|
||||
{
|
||||
get => base.VirtualProperty;
|
||||
set => base.VirtualProperty = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseClassWithVirtualPropertyDataMemberOnVirtualOnly
|
||||
{
|
||||
[DataMember]
|
||||
public virtual int VirtualProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class DerivedClassThatOverridesPropertyDataMemberOnVirtualOnly : BaseClassWithVirtualPropertyDataMemberOnVirtualOnly
|
||||
{
|
||||
public override int VirtualProperty
|
||||
{
|
||||
get => base.VirtualProperty;
|
||||
set => base.VirtualProperty = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseClassWithVirtualPropertyOrdinalKey
|
||||
{
|
||||
[DataMember(Order = 0)]
|
||||
public virtual int VirtualProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class DerivedClassThatOverridesPropertyOrdinalKey : BaseClassWithVirtualPropertyOrdinalKey
|
||||
{
|
||||
[DataMember(Order = 0)]
|
||||
public override int VirtualProperty
|
||||
{
|
||||
get => base.VirtualProperty;
|
||||
set => base.VirtualProperty = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseClassWithVirtualPropertyDataMemberOnOverrideOnlyOrdinalKey
|
||||
{
|
||||
public virtual int VirtualProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class DerivedClassThatOverridesPropertyDataMemberOnOverrideOnlyOrdinalKey : BaseClassWithVirtualPropertyDataMemberOnOverrideOnlyOrdinalKey
|
||||
{
|
||||
[DataMember(Order = 0)]
|
||||
public override int VirtualProperty
|
||||
{
|
||||
get => base.VirtualProperty;
|
||||
set => base.VirtualProperty = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class BaseClassWithVirtualPropertyDataMemberOnVirtualOnlyOrdinalKey
|
||||
{
|
||||
[DataMember(Order = 0)]
|
||||
public virtual int VirtualProperty { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class DerivedClassThatOverridesPropertyDataMemberOnVirtualOnlyOrdinalKey : BaseClassWithVirtualPropertyDataMemberOnVirtualOnlyOrdinalKey
|
||||
{
|
||||
public override int VirtualProperty
|
||||
{
|
||||
get => base.VirtualProperty;
|
||||
set => base.VirtualProperty = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class TwoProperties
|
||||
{
|
||||
[DataMember]
|
||||
public string Prop1 { get; set; } = "Uninitialized";
|
||||
|
||||
[DataMember]
|
||||
public string Prop2 { get; set; } = "Uninitialized";
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class TwoPropertiesOrdinalKey
|
||||
{
|
||||
[DataMember(Order = 0)]
|
||||
public string Prop1 { get; set; } = "Uninitialized";
|
||||
|
||||
[DataMember(Order = 1)]
|
||||
public string Prop2 { get; set; } = "Uninitialized";
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class TestMessageWithReadOnlyField
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче