Skip to content

Commit f34c23f

Browse files
committed
Fix empty serializable members with packer/unpacker interfaces should be serialized. #202
This commit add * Unit tests for new specs. * Relaxes validation to allow types which implement I[Un][Async]Packable fully but have no members. * Add additional validation to check such types implements pair of interfaces or not.
1 parent 23effe8 commit f34c23f

17 files changed

Lines changed: 3680 additions & 81 deletions

CHANGES.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ Release 0.9.0 beta1 2016/09/24
619619
BUG FIXES
620620
* Fix nuspec to prevent old NuGet clients which do not support .NET Standard TFMs. Issue #177.
621621

622-
Release 0.9.0 (planned)
622+
Release 0.9.0 beta2 2017/2/11
623623

624624
BREAKING CHANGES
625625
* MessagePackObject comparison which have large binary data will be about 2x - 18x slower in .NET 3.5/4.5/4.6(other platforms will not be affected).
@@ -641,4 +641,4 @@ Release 0.9.0 (planned)
641641
* Fix Windows Native build error. Issue #206.
642642
* Fix built-in collection serializers such as List<T> serializer causes SecurityException when the program run in restricted environment like Silverlight. Issue #205.
643643
* 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)
644-
644+
* Fix types which implement IPackable and IUnpackable but do not have any members cannot be serialized. Issue #202

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
using System.Globalization;
2929
using System.Linq;
3030
using System.Reflection;
31+
using System.Runtime.Serialization;
3132
#if FEATURE_TAP
3233
using System.Threading;
3334
using System.Threading.Tasks;
@@ -168,6 +169,19 @@ private TConstruct BuildIPackablePackToCore( TContext context, Type @interface )
168169

169170
private void BuildObjectPackTo( TContext context, SerializationTarget targetInfo, bool isAsync )
170171
{
172+
if ( targetInfo.Members.Count == 0 )
173+
{
174+
throw new SerializationException(
175+
String.Format(
176+
CultureInfo.CurrentCulture,
177+
isAsync
178+
? "At least one serializable member is required because type '{0}' does not implement IAsyncPackable interface."
179+
: "At least one serializable member is required because type '{0}' does not implement IPackable interface.",
180+
this.TargetType
181+
)
182+
);
183+
}
184+
171185
var methodName =
172186
#if FEATURE_TAP
173187
isAsync ? MethodName.PackToAsyncCore :
@@ -758,6 +772,19 @@ private IEnumerable<TConstruct> BuildIUnpackableUnpackFromCore( TContext context
758772

759773
private void BuildObjectUnpackFrom( TContext context, SerializationTarget targetInfo, bool isAsync )
760774
{
775+
if ( targetInfo.Members.Count == 0 )
776+
{
777+
throw new SerializationException(
778+
String.Format(
779+
CultureInfo.CurrentCulture,
780+
isAsync
781+
? "At least one serializable member is required because type '{0}' does not implement IAsyncUnpackable interface."
782+
: "At least one serializable member is required because type '{0}' does not implement IUnpackable interface.",
783+
this.TargetType
784+
)
785+
);
786+
}
787+
761788
/*
762789
* #if T is IUnpackable
763790
* result.UnpackFromMessage( unpacker );

src/MsgPack/Serialization/CodeDomSerializers/CodeDomContext.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
using System.Linq;
3333
using System.Reflection;
3434
using System.Security;
35-
using System.Text;
3635
#if FEATURE_TAP
3736
using System.Threading;
3837
using System.Threading.Tasks;

src/MsgPack/Serialization/CodeDomSerializers/CodeDomSerializerBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1605,7 +1605,7 @@ private void Finish( CodeDomContext context, SerializationTarget targetInfo, boo
16051605
ctor.Statements.AddRange(
16061606
this.EmitMemberListInitialization( context, targetInfo ).AsStatements().ToArray()
16071607
);
1608-
}
1608+
}
16091609
}
16101610
} // if( targetInfo != null )
16111611

src/MsgPack/Serialization/ReflectionSerializers/ReflectionSerializerHelper.cs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public static MessagePackSerializer<T> CreateReflectionEnumMessagePackSerializer
5757
return
5858
ReflectionExtensions.CreateInstancePreservingExceptionType<MessagePackSerializer<T>>(
5959
typeof( ReflectionEnumMessagePackSerializer<> ).MakeGenericType( typeof( T ) ),
60-
context
60+
context
6161
);
6262
#else
6363
return MessagePackSerializer.Wrap<T>( context, new ReflectionEnumMessagePackSerializer( context, typeof( T ) ) );
@@ -221,7 +221,7 @@ public static Action<object, object> GetAddItem( Type targetType, CollectionTrai
221221
catch ( ArgumentException )
222222
{
223223
#endif // !AOT || AOT_CHECK
224-
return ( collection, item ) => collectionTraits.AddMethod.InvokePreservingExceptionType( collection, item );
224+
return ( collection, item ) => collectionTraits.AddMethod.InvokePreservingExceptionType( collection, item );
225225
#if !AOT || AOT_CHECK
226226
}
227227
#endif // !AOT || AOT_CHECK
@@ -235,10 +235,65 @@ public static void GetMetadata(
235235
out Action<object, object>[] setters,
236236
out MemberInfo[] memberInfos,
237237
out DataMemberContract[] contracts,
238-
out MessagePackSerializer[] serializers )
238+
out MessagePackSerializer[] serializers
239+
)
239240
{
240241
SerializationTarget.VerifyCanSerializeTargetType( context, targetType );
241242

243+
if ( members.Count == 0 )
244+
{
245+
if ( !typeof( IPackable ).IsAssignableFrom( targetType ) )
246+
{
247+
throw new SerializationException(
248+
String.Format(
249+
CultureInfo.CurrentCulture,
250+
"At least one serializable member is required because type '{0}' does not implement IPackable interface.",
251+
targetType
252+
)
253+
);
254+
}
255+
256+
if ( !typeof( IUnpackable ).IsAssignableFrom( targetType ) )
257+
{
258+
throw new SerializationException(
259+
String.Format(
260+
CultureInfo.CurrentCulture,
261+
"At least one serializable member is required because type '{0}' does not implement IUnpackable interface.",
262+
targetType
263+
)
264+
);
265+
}
266+
267+
#if FEATURE_TAP
268+
if ( context.SerializerOptions.WithAsync )
269+
{
270+
if ( !typeof( IAsyncPackable ).IsAssignableFrom( targetType ) )
271+
{
272+
throw new SerializationException(
273+
String.Format(
274+
CultureInfo.CurrentCulture,
275+
"At least one serializable member is required because type '{0}' does not implement IAsyncPackable interface.",
276+
targetType
277+
)
278+
);
279+
}
280+
281+
if ( !typeof( IAsyncUnpackable ).IsAssignableFrom( targetType ) )
282+
{
283+
throw new SerializationException(
284+
String.Format(
285+
CultureInfo.CurrentCulture,
286+
"At least one serializable member is required because type '{0}' does not implement IAsyncUnpackable interface.",
287+
targetType
288+
)
289+
);
290+
}
291+
}
292+
293+
#endif // FEATURE_TAP
294+
295+
}
296+
242297
getters = new Func<object, object>[ members.Count ];
243298
setters = new Action<object, object>[ members.Count ];
244299
memberInfos = new MemberInfo[ members.Count ];
@@ -364,7 +419,7 @@ public static Func<int, object> CreateCollectionInstanceFactory( Type abstractTy
364419
{
365420
case 0:
366421
{
367-
return _ =>
422+
return _ =>
368423
#if !UNITY
369424
( T )
370425
#endif // !UNITY

0 commit comments

Comments
 (0)