Skip to content

Commit 6bb729e

Browse files
committed
Fix Unity AOT does not recognize custom attribute correctly.
This fix reverts CustomAttributeData based approach to attribute instance based approach because Unity's IL2CPP does not handle them correctly. Also, this fix remove wrong comment because Unity's mono also returns -1 for default value of Order. This may be default behavior. Note that there is a difference between Silverlight and others because SL uses Attribute instead of CustomAttributeData, so: * NilImplication is returned as is instead of its underlying primitive(Int32). * Id is returned from the property instead of constructor arguments.
1 parent f1836ed commit 6bb729e

File tree

2 files changed

+162
-21
lines changed

2 files changed

+162
-21
lines changed

src/MsgPack/ReflectionAbstractions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,11 @@ public static Type GetAttributeType( this CustomAttributeData source )
435435

436436
public static string GetMemberName( this CustomAttributeNamedArgument source )
437437
{
438+
if ( source.MemberInfo == null )
439+
{
440+
return null;
441+
}
442+
438443
return source.MemberInfo.Name;
439444
}
440445

@@ -489,6 +494,11 @@ public static IEnumerable<NamedArgument> GetNamedArguments( this Attribute attri
489494
.Select( m => new NamedArgument( attribute, m ) );
490495
}
491496
#else
497+
public static IList<CustomAttributeTypedArgument> GetConstructorArguments( this CustomAttributeData source )
498+
{
499+
return source.ConstructorArguments;
500+
}
501+
492502
public static IEnumerable<CustomAttributeNamedArgument> GetNamedArguments( this CustomAttributeData source )
493503
{
494504
return source.NamedArguments;

src/MsgPack/Serialization/SerializationTarget.cs

Lines changed: 152 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -368,15 +368,28 @@ private static IEnumerable<SerializingMember> GetTargetMembers( Type type )
368368
Contract.Assert( type != null, "type != null" );
369369

370370
var members = GetDistinctMembers( type );
371-
var filtered = members.Where( item => item.GetCustomAttributesData().Any( a => a.GetAttributeType().FullName == MessagePackMemberAttributeTypeName ) ).ToArray();
371+
var filtered = members.Where( item =>
372+
#if !UNITY
373+
item.GetCustomAttributesData().Any( a => a.GetAttributeType().FullName == MessagePackMemberAttributeTypeName )
374+
#else
375+
item.GetCustomAttributes( typeof( MessagePackMemberAttribute ), true ).Any()
376+
#endif // !UNITY
377+
).ToArray();
372378

373379
if ( filtered.Length > 0 )
374380
{
375381
return GetAnnotatedMembersWithDuplicationDetection( type, filtered );
376382
}
377383

378-
if ( type.GetCustomAttributesData().Any( attr =>
379-
attr.GetAttributeType().FullName == "System.Runtime.Serialization.DataContractAttribute" ) )
384+
if (
385+
#if !UNITY
386+
type.GetCustomAttributesData().Any( attr =>
387+
attr.GetAttributeType().FullName == "System.Runtime.Serialization.DataContractAttribute" )
388+
#else
389+
type.GetCustomAttributes( true ).Any( attr =>
390+
attr.GetType().FullName == "System.Runtime.Serialization.DataContractAttribute" )
391+
#endif // !UNITY
392+
)
380393
{
381394
return GetSystemRuntimeSerializationCompatibleMembers( members );
382395
}
@@ -388,7 +401,11 @@ private static IEnumerable<SerializingMember> GetAnnotatedMembersWithDuplication
388401
{
389402
var duplicated =
390403
filtered.FirstOrDefault(
404+
#if !UNITY
391405
member => member.GetCustomAttributesData().Any( a => a.GetAttributeType().FullName == MessagePackIgnoreAttributeTypeName )
406+
#else
407+
member => member.GetCustomAttributes( typeof( MessagePackIgnoreAttribute ), true ).Any()
408+
#endif // !UNITY
392409
);
393410

394411
if ( duplicated != null )
@@ -406,12 +423,72 @@ private static IEnumerable<SerializingMember> GetAnnotatedMembersWithDuplication
406423
return
407424
filtered.Select(
408425
member =>
409-
new SerializingMember(
410-
member,
411-
new DataMemberContract( member, member.GetCustomAttribute<MessagePackMemberAttribute>() )
412-
)
413-
);
426+
{
427+
#if !UNITY
428+
var attribute = member.GetCustomAttributesData().Single( a => a.GetAttributeType().FullName == MessagePackMemberAttributeTypeName );
429+
return
430+
new SerializingMember(
431+
member,
432+
new DataMemberContract(
433+
member,
434+
( string )GetAttributeProperty( MessagePackMemberAttributeTypeName, attribute, "Name" ),
435+
#if !SILVERLIGHT
436+
( NilImplication )( ( int? )GetAttributeProperty( MessagePackMemberAttributeTypeName, attribute, "NilImplication" ) ).GetValueOrDefault(),
437+
( int? )GetAttributeArgument( MessagePackMemberAttributeTypeName, attribute, 0 )
438+
#else
439+
( NilImplication )GetAttributeProperty( MessagePackMemberAttributeTypeName, attribute, "NilImplication" ),
440+
( int? )GetAttributeProperty( MessagePackMemberAttributeTypeName, attribute, "Id" )
441+
#endif // !SILVERLIGHT
442+
)
443+
);
444+
#else
445+
var attribute = member.GetCustomAttributes( typeof( MessagePackMemberAttribute ), true ).Single() as MessagePackMemberAttribute;
446+
return
447+
new SerializingMember(
448+
member,
449+
new DataMemberContract(
450+
member,
451+
attribute.Name,
452+
attribute.NilImplication,
453+
attribute.Id
454+
)
455+
);
456+
#endif // !UNITY
457+
}
458+
);
459+
}
460+
461+
#if !UNITY
462+
#if !SILVERLIGHT
463+
private static object GetAttributeArgument( string attributeName, CustomAttributeData attribute, int index )
464+
{
465+
var arguments = attribute.GetConstructorArguments();
466+
if ( arguments.Count < index )
467+
{
468+
// Use default.
469+
return null;
470+
}
471+
472+
return arguments[ index ].Value;
473+
}
474+
#endif // !SILVERLIGHT
475+
476+
#if !SILVERLIGHT
477+
private static object GetAttributeProperty( string attributeName, CustomAttributeData attribute, string propertyName )
478+
#else
479+
private static object GetAttributeProperty( string attributeName, Attribute attribute, string propertyName )
480+
#endif // !SILVERLIGHT
481+
{
482+
var property = attribute.GetNamedArguments().SingleOrDefault( a => a.GetMemberName() == propertyName );
483+
if ( property.GetMemberName() == null )
484+
{
485+
// Use default.
486+
return null;
487+
}
488+
489+
return property.GetTypedValue().Value;
414490
}
491+
#endif // !UNITY
415492

416493
private static IEnumerable<SerializingMember> GetSystemRuntimeSerializationCompatibleMembers( MemberInfo[] members )
417494
{
@@ -422,15 +499,23 @@ private static IEnumerable<SerializingMember> GetSystemRuntimeSerializationCompa
422499
{
423500
member = item,
424501
data =
502+
#if !UNITY
425503
item.GetCustomAttributesData()
426504
.FirstOrDefault(
427505
data => data.GetAttributeType().FullName == "System.Runtime.Serialization.DataMemberAttribute"
428506
)
507+
#else
508+
item.GetCustomAttributes( true )
509+
.FirstOrDefault(
510+
data => data.GetType().FullName == "System.Runtime.Serialization.DataMemberAttribute"
511+
)
512+
#endif // !UNITY
429513
}
430514
).Where( item => item.data != null )
431515
.Select(
432516
item =>
433517
{
518+
#if !UNITY
434519
var name =
435520
item.data.GetNamedArguments()
436521
.Where( arg => arg.GetMemberName() == "Name" )
@@ -439,29 +524,57 @@ private static IEnumerable<SerializingMember> GetSystemRuntimeSerializationCompa
439524
var id =
440525
item.data.GetNamedArguments()
441526
.Where( arg => arg.GetMemberName() == "Order" )
442-
#if !UNITY
443527
.Select( arg => ( int? )arg.GetTypedValue().Value )
444-
#else
445-
.Select( arg => arg.GetTypedValue().Value )
446-
#endif
447528
.FirstOrDefault();
448-
#if SILVERLIGHT
449529
if ( id == -1 )
450530
{
451-
// Shim for Silverlight returns -1 because GetNamedArguments() extension method cannot recognize whether the argument was actually specified or not.
452531
id = null;
453532
}
454-
#endif // SILVERLIGHT
455533

456534
return
457535
new SerializingMember(
458536
item.member,
459-
#if !UNITY
460537
new DataMemberContract( item.member, name, NilImplication.MemberDefault, id )
538+
);
461539
#else
462-
new DataMemberContract( item.member, name, NilImplication.MemberDefault, ( int? )id )
463-
#endif // !UNITY
540+
var nameProperty = item.data.GetType().GetProperty( "Name" );
541+
var orderProperty = item.data.GetType().GetProperty( "Order" );
542+
543+
if ( nameProperty == null || !nameProperty.CanRead || nameProperty.GetGetMethod().GetParameters().Length > 0 )
544+
{
545+
throw new SerializationException(
546+
String.Format(
547+
CultureInfo.CurrentCulture,
548+
"Failed to get Name property from {0} type.",
549+
item.data.GetType().AssemblyQualifiedName
550+
)
464551
);
552+
}
553+
554+
if( orderProperty == null || !orderProperty.CanRead || orderProperty.GetGetMethod().GetParameters().Length > 0 )
555+
{
556+
throw new SerializationException(
557+
String.Format(
558+
CultureInfo.CurrentCulture,
559+
"Failed to get Order property from {0} type.",
560+
item.data.GetType().AssemblyQualifiedName
561+
)
562+
);
563+
}
564+
565+
var name = ( string )nameProperty.GetValue( item.data, null );
566+
var id = ( int? )orderProperty.GetValue( item.data, null );
567+
if ( id == -1 )
568+
{
569+
id = null;
570+
}
571+
572+
return
573+
new SerializingMember(
574+
item.member,
575+
new DataMemberContract( item.member, name, NilImplication.MemberDefault, id )
576+
);
577+
#endif // !UNITY
465578
}
466579
);
467580
}
@@ -471,8 +584,14 @@ private static IEnumerable<SerializingMember> GetPublicUnpreventedMembers( Membe
471584
return members.Where(
472585
member =>
473586
member.GetIsPublic()
474-
&& !member.GetCustomAttributesData()
587+
&& !member
588+
#if !UNITY
589+
.GetCustomAttributesData()
475590
.Select( data => data.GetAttributeType().FullName )
591+
#else
592+
.GetCustomAttributes( true )
593+
.Select( data => data.GetType().FullName )
594+
#endif // !UNITY
476595
.Any( attr =>
477596
attr == "MsgPack.Serialization.MessagePackIgnoreAttribute"
478597
|| attr == "System.Runtime.Serialization.IgnoreDataMemberAttribute"
@@ -484,7 +603,7 @@ private static IEnumerable<SerializingMember> GetPublicUnpreventedMembers( Membe
484603
private static bool IsNonSerializedField( MemberInfo member )
485604
{
486605
var asField = member as FieldInfo;
487-
if( asField == null )
606+
if ( asField == null )
488607
{
489608
return false;
490609
}
@@ -586,7 +705,19 @@ private static ConstructorInfo FindDeserializationConstructor( SerializationCont
586705

587706
private static IList<ConstructorInfo> FindExplicitDeserializationConstructors( IEnumerable<ConstructorInfo> construtors )
588707
{
589-
return construtors.Where( ctor => ctor.GetCustomAttributesData().Any( a => a.GetAttributeType().FullName == MessagePackDeserializationConstructorAttributeTypeName ) ).ToArray();
708+
return
709+
construtors
710+
.Where( ctor =>
711+
#if !UNITY
712+
ctor.GetCustomAttributesData().Any( a =>
713+
a.GetAttributeType().FullName
714+
#else
715+
ctor.GetCustomAttributes( true ).Any( a =>
716+
a.GetType().FullName
717+
#endif // !UNITY
718+
== MessagePackDeserializationConstructorAttributeTypeName
719+
)
720+
).ToArray();
590721
}
591722

592723
private static SerializationException NewTypeCannotBeSerializedException( Type targetType )

0 commit comments

Comments
 (0)