Skip to content

Commit dca72f3

Browse files
authored
Merge pull request #236 from msgpack/fix/#233
Fix constructor based deserialization code gen #233
2 parents 551b6d2 + b627c2b commit dca72f3

18 files changed

+349
-238
lines changed

CHANGES.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,3 +640,8 @@ Release 0.9.0 beta2 2017/2/12
640640
* Fix null items of complex type in List<T> or Dictionary<TKey, TValue> will not be deserialized as null. Issue #211. (from 0.8.1)
641641
* Fix types which implement IPackable and IUnpackable but do not have any members cannot be serialized. Issue #202
642642
* Fix Windows Native build error. Issue #206.
643+
644+
Release 0.9.0 RC1 T.B.D.
645+
646+
BUG FIXES
647+
* Fix constructor deserialization fails if the constructor parameters order is not lexical. Issue #233

build/Version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.9.0-beta2
1+
0.9.0-rc1

samples/Samples/Sample07_ConstructorBasedDeserialization.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void DoConstructorBasedDeserialization()
4040
{
4141
// As of 0.8, constructor based deserialization is relaxed.
4242
// 1. If the type have a constructor with MessagePackDeserializationConstructorAttribute, then it will be used for deserialization.
43-
// 2. Else, ff the type have a default public constructor then it will be used for deserialization.
43+
// 2. Else, if the type have a default public constructor then it will be used for deserialization.
4444
// 3. Otherwise, most parameterful constructor will be used.
4545

4646
var serializerForSimpleRecord = MessagePackSerializer.Get<MySimpleRecordClass>();

src/MsgPack/Serialization/AbstractSerializers/DynamicUnpackingContext.cs

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/MsgPack/Serialization/AbstractSerializers/SerializerBuilder`2.Object.cs

Lines changed: 14 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -845,12 +845,6 @@ private TConstruct EmitObjectUnpackFromCore( TContext context, SerializationTarg
845845
#endif // FEATURE_TAP
846846
;
847847

848-
int constructorParameterIndex = 0;
849-
var fieldNames =
850-
targetInfo.IsConstructorDeserialization
851-
? targetInfo.DeserializationConstructor.GetParameters().Select( p => p.Name ).ToArray()
852-
: targetInfo.Members.Where( m => m.MemberName != null ).Select( m => m.MemberName ).ToArray();
853-
854848
for ( int i = 0; i < targetInfo.Members.Count; i++ )
855849
{
856850
var count = i;
@@ -881,33 +875,16 @@ private TConstruct EmitObjectUnpackFromCore( TContext context, SerializationTarg
881875
}
882876
else
883877
{
878+
var name = targetInfo.Members[ count ].MemberName;
879+
Contract.Assert( !String.IsNullOrEmpty( name ), targetInfo.Members[ count ] + "@" + i + " does not have member name.");
884880
var unpackedItem =
885881
context.DefineUnpackedItemParameterInSetValueMethods( targetInfo.Members[ count ].Member.GetMemberValueType() );
886882
Func<TConstruct> storeValueStatementEmitter;
887-
if ( unpackingContext.VariableType.TryGetRuntimeType() == typeof( DynamicUnpackingContext ) )
888-
{
889-
storeValueStatementEmitter =
890-
() =>
891-
this.EmitInvokeVoidMethod(
892-
context,
893-
context.UnpackingContextInSetValueMethods,
894-
Metadata._DynamicUnpackingContext.Set,
895-
this.MakeStringLiteral( context, fieldNames[ count ] ),
896-
targetInfo.Members[ count ].Member.GetMemberValueType().GetIsValueType()
897-
? this.EmitBoxExpression(
898-
context,
899-
unpackedItem.ContextType,
900-
unpackedItem
901-
) : unpackedItem
902-
);
903-
}
904-
else if ( targetInfo.IsConstructorDeserialization || this.TargetType.GetIsValueType() )
883+
if ( targetInfo.IsConstructorDeserialization || this.TargetType.GetIsValueType() )
905884
{
906-
var name = fieldNames[ constructorParameterIndex ];
907885
storeValueStatementEmitter =
908886
() =>
909887
this.EmitSetField( context, context.UnpackingContextInSetValueMethods, unpackingContext.Type, name, unpackedItem );
910-
constructorParameterIndex++;
911888
}
912889
else
913890
{
@@ -1013,7 +990,7 @@ private UnpackingContextInfo EmitObjectUnpackingContextInitialization( TContext
1013990
{
1014991
var constructorParameters = targetInfo.DeserializationConstructor.GetParameters();
1015992
var contextFields =
1016-
constructorParameters.Select( p => new KeyValuePair<string, TypeDefinition>( p.Name, p.ParameterType ) ).ToArray();
993+
constructorParameters.Select( ( p, i ) => new KeyValuePair<string, TypeDefinition>( targetInfo.GetCorrespondingMemberName( i ) ?? ( "__OrphanParameter" + i.ToString( CultureInfo.InvariantCulture ) ), p.ParameterType ) ).ToArray();
1017994
var constructorArguments = new List<TConstruct>( constructorParameters.Length );
1018995
var mappableConstructorArguments = new HashSet<string>();
1019996
var initializationStatements =
@@ -1148,39 +1125,7 @@ IEnumerable<TConstruct> argumentInitializers
11481125
unpackingContext.Statements.AddRange( argumentInitializers );
11491126

11501127
unpackingContext.Statements.Add(
1151-
unpackingContext.VariableType.TryGetRuntimeType() == typeof( DynamicUnpackingContext )
1152-
? this.EmitSequentialStatements(
1153-
context,
1154-
TypeDefinition.VoidType,
1155-
new[]
1156-
{
1157-
this.EmitStoreVariableStatement(
1158-
context,
1159-
unpackingContext.Variable,
1160-
this.EmitCreateNewObjectExpression(
1161-
context,
1162-
unpackingContext.Variable,
1163-
unpackingContext.Constructor,
1164-
this.MakeInt32Literal( context, constructorArguments.Count )
1165-
)
1166-
)
1167-
}.Concat(
1168-
constructorArguments.Select( ( a, i ) =>
1169-
this.EmitInvokeVoidMethod(
1170-
context,
1171-
unpackingContext.Variable,
1172-
Metadata._DynamicUnpackingContext.Set,
1173-
this.MakeStringLiteral( context, contextFields[ i ].Key ),
1174-
a.ContextType.ResolveRuntimeType().GetIsValueType()
1175-
? this.EmitBoxExpression(
1176-
context,
1177-
a.ContextType,
1178-
a
1179-
) : a
1180-
)
1181-
)
1182-
)
1183-
) : this.EmitStoreVariableStatement(
1128+
this.EmitStoreVariableStatement(
11841129
context,
11851130
unpackingContext.Variable,
11861131
this.EmitCreateNewObjectExpression(
@@ -1224,26 +1169,15 @@ private IEnumerable<TConstruct> EmitCreateObjectFromContextCore(
12241169
context,
12251170
result,
12261171
member,
1227-
unpackingContext.VariableType.TryGetRuntimeType() == typeof( DynamicUnpackingContext )
1228-
? this.EmitUnboxAnyExpression(
1229-
context,
1230-
field.Value,
1231-
this.EmitInvokeMethodExpression(
1232-
context,
1233-
context.UnpackingContextInCreateObjectFromContext,
1234-
Metadata._DynamicUnpackingContext.Get,
1235-
this.MakeStringLiteral( context, field.Key )
1236-
)
1237-
)
1238-
: this.EmitGetFieldExpression(
1239-
context,
1240-
context.UnpackingContextInCreateObjectFromContext,
1241-
new FieldDefinition(
1242-
unpackingContext.Type,
1243-
field.Key,
1244-
field.Value
1245-
)
1172+
this.EmitGetFieldExpression(
1173+
context,
1174+
context.UnpackingContextInCreateObjectFromContext,
1175+
new FieldDefinition(
1176+
unpackingContext.Type,
1177+
field.Key,
1178+
field.Value
12461179
)
1180+
)
12471181
);
12481182
}
12491183

@@ -1523,18 +1457,7 @@ private IEnumerable<TConstruct> EmitInvokeDeserializationConstructorStatementsCo
15231457
constructor,
15241458
fields.Select(
15251459
f =>
1526-
unpackingContext.ContextType.TryGetRuntimeType() == typeof( DynamicUnpackingContext )
1527-
? this.EmitUnboxAnyExpression(
1528-
context,
1529-
f.Value,
1530-
this.EmitInvokeMethodExpression(
1531-
context,
1532-
unpackingContext,
1533-
Metadata._DynamicUnpackingContext.Get,
1534-
this.MakeStringLiteral( context, f.Key )
1535-
)
1536-
)
1537-
: this.EmitGetFieldExpression( context, unpackingContext, new FieldDefinition( unpackingContext.ContextType, f.Key, f.Value ) )
1460+
this.EmitGetFieldExpression( context, unpackingContext, new FieldDefinition( unpackingContext.ContextType, f.Key, f.Value ) )
15381461
).ToArray()
15391462
)
15401463
);

src/MsgPack/Serialization/AbstractSerializers/SerializerBuilder`2.Tuple.cs

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -350,18 +350,8 @@ private IEnumerable<TConstruct> BuildTupleUnpackFromCore( TContext context, ILis
350350
setUnpackValueOfMethodName,
351351
false, // isStatic
352352
TypeDefinition.VoidType,
353-
() => unpackingContext.VariableType.TryGetRuntimeType() == typeof( DynamicUnpackingContext )
354-
? this.EmitInvokeVoidMethod(
355-
context,
356-
context.UnpackingContextInSetValueMethods,
357-
Metadata._DynamicUnpackingContext.Set,
358-
this.MakeStringLiteral( context, propertyName ),
359-
this.EmitBoxExpression(
360-
context,
361-
itemTypes[ index ],
362-
unpackedItem
363-
)
364-
) : this.EmitSetField(
353+
() =>
354+
this.EmitSetField(
365355
context,
366356
context.UnpackingContextInSetValueMethods,
367357
unpackingContext.VariableType,
@@ -383,25 +373,15 @@ private IEnumerable<TConstruct> BuildTupleUnpackFromCore( TContext context, ILis
383373
var gets =
384374
Enumerable.Range( nest * 7, Math.Min( itemTypes.Count - nest * 7, 7 ) )
385375
.Select( i =>
386-
unpackingContext.VariableType.TryGetRuntimeType() == typeof( DynamicUnpackingContext )
387-
? this.EmitUnboxAnyExpression(
388-
context,
389-
itemTypes[ i ],
390-
this.EmitInvokeMethodExpression(
391-
context,
392-
context.UnpackingContextInCreateObjectFromContext,
393-
Metadata._DynamicUnpackingContext.Get,
394-
this.MakeStringLiteral( context, SerializationTarget.GetTupleItemNameFromIndex( i ) )
395-
)
396-
) : this.EmitGetFieldExpression(
397-
context,
398-
context.UnpackingContextInCreateObjectFromContext,
399-
new FieldDefinition(
400-
unpackingContext.VariableType,
401-
SerializationTarget.GetTupleItemNameFromIndex( i ),
402-
itemTypes[ i ]
403-
)
376+
this.EmitGetFieldExpression(
377+
context,
378+
context.UnpackingContextInCreateObjectFromContext,
379+
new FieldDefinition(
380+
unpackingContext.VariableType,
381+
SerializationTarget.GetTupleItemNameFromIndex( i ),
382+
itemTypes[ i ]
404383
)
384+
)
405385
);
406386
if ( currentTuple != null )
407387
{
@@ -499,9 +479,7 @@ out constructor
499479
context,
500480
unpackingContext.Variable,
501481
unpackingContext.Constructor,
502-
unpackingContext.VariableType.TryGetRuntimeType() == typeof( DynamicUnpackingContext )
503-
? new[] { this.MakeInt32Literal( context, itemTypes.Count ) }
504-
: itemTypes.Select( t => this.MakeDefaultLiteral( context, t ) ).ToArray()
482+
itemTypes.Select( t => this.MakeDefaultLiteral( context, t ) ).ToArray()
505483
)
506484
)
507485
);

src/MsgPack/Serialization/Metadata/_DynamicUnpackingContext.cs

Lines changed: 0 additions & 38 deletions
This file was deleted.

test/MsgPack.UnitTest.CodeDom/Serialization/ArrayCodeDomBasedAutoMessagePackSerializerTest.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,6 +3855,31 @@ public void TestOptionalConstructorString_Success()
38553855
}
38563856
}
38573857

3858+
// Issue233
3859+
[Test]
3860+
public void TestConstructorDeserializationWithParametersNotInLexicalOrder()
3861+
{
3862+
var endpoints =
3863+
new EndpointList(
3864+
"Test String One",
3865+
new Dictionary<string, string[]>
3866+
{
3867+
{ "ConfigService", new [] { "ur1", "ur2" } },
3868+
{ "TestService", new [] { "ur1", "ur2" } }
3869+
},
3870+
"Test String Two"
3871+
);
3872+
3873+
var context = new SerializationContext();
3874+
var ser = context.GetSerializer<EndpointList>();
3875+
var bytes = ser.PackSingleObject( endpoints );
3876+
var endpointsDeser = ser.UnpackSingleObject( bytes );
3877+
3878+
Assert.That( endpointsDeser.StringOne, Is.EqualTo( endpoints.StringOne ) );
3879+
Assert.That( endpointsDeser.StringTwo, Is.EqualTo( endpoints.StringTwo ) );
3880+
Assert.That( endpointsDeser.Endpoints, Is.EqualTo( endpoints.Endpoints ) );
3881+
}
3882+
38583883
[Test]
38593884
public void TestCollection_Success()
38603885
{

0 commit comments

Comments
 (0)