private static bool JudgeNullable( Type type ) { if ( !type.GetIsValueType() ) { // reference type. return true; } if ( type == typeof( MessagePackObject ) ) { // can be MPO.Nil. return true; } if ( type.GetIsGenericType() && type.GetGenericTypeDefinition() == typeof( Nullable<> ) ) { // Nullable<T> return true; } return false; }
public static SerializationTarget Prepare( SerializationContext context, Type targetType ) { var getters = GetTargetMembers( targetType ).OrderBy( entry => entry.Contract.Id ).ToArray(); if ( getters.Length == 0 ) { throw new SerializationException( String.Format( CultureInfo.CurrentCulture, "Cannot serialize type '{0}' because it does not have any serializable fields nor properties.", targetType ) ); } var memberCandidates = getters.Where( entry => CheckTargetEligibility( entry.Member ) ).ToArray(); if ( memberCandidates.Length == 0 ) { var constructor = FindDeserializationConstructor( targetType ); return new SerializationTarget( ComplementMembers( getters, context, targetType ), constructor ); } var defaultConstructor = targetType.GetConstructor( ReflectionAbstractions.EmptyTypes ); if ( defaultConstructor == null && !targetType.GetIsValueType() ) { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructor( targetType ); } // Because members' order is equal to declared order is NOT guaranteed, so explicit ordering is required. IList<SerializingMember> members; if ( memberCandidates.All( item => item.Contract.Id == DataMemberContract.UnspecifiedId ) ) { // Alphabetical order. members = memberCandidates.OrderBy( item => item.Contract.Name ).ToArray(); } else { // ID order. members = ComplementMembers( memberCandidates, context, targetType ); } return new SerializationTarget( members, defaultConstructor ); }
private static PropertyInfo GetCollectionTCountProperty( Type targetType, Type elementType ) { if ( !targetType.GetIsValueType() && targetType.Implements( typeof( ICollection<> ) ) ) { return typeof( ICollection<> ).MakeGenericType( elementType ).GetProperty( "Count" ); } var property = targetType.GetProperty( "Count" ); if ( property != null && property.PropertyType == typeof( int ) && property.GetIndexParameters().Length == 0 ) { return property; } return null; }
/// <summary> /// Emit array element storing instructions. /// Post condition is evaluation stack will no be modified as previous state. /// </summary> /// <param name="elementType"><see cref="Type"/> of array element. This can be generaic parameter.</param> /// <param name="arrayLoadingEmitter"> /// Delegate to emittion of array loading instruction. /// 1st argument is this instance. /// Post condition is that exactly one target array will be added on the top of stack and its element type is <paramref name="elementType"/>. /// </param> /// <param name="indexEmitter"> /// Delegate to emittion of array index. /// 1st argument is this instance. /// Post condition is that int4 or int8 type value will be added on the top of stack and its element type is <paramref name="elementType"/>. /// </param> /// <param name="elementLoadingEmitter"> /// Delegate to emittion of storing element loading instruction. /// 1st argument is this instance. /// Post condition is that exactly one storing element will be added on the top of stack and its type is <paramref name="elementType"/> compatible. /// </param> public void EmitAnyStelem( Type elementType, Action<TracingILGenerator> arrayLoadingEmitter, Action<TracingILGenerator> indexEmitter, Action<TracingILGenerator> elementLoadingEmitter ) { Contract.Assert( elementType != null ); Contract.Assert( indexEmitter != null ); Contract.Assert( arrayLoadingEmitter != null ); Contract.Assert( elementLoadingEmitter != null ); arrayLoadingEmitter( this ); indexEmitter( this ); elementLoadingEmitter( this ); if ( elementType.IsGenericParameter ) { this.EmitStelem( elementType ); return; } if ( !elementType.GetIsValueType() ) { // ref this.EmitStelem_Ref(); return; } #if !NETSTANDARD1_1 && !NETSTANDARD1_3 switch ( Type.GetTypeCode( elementType ) ) #else switch ( NetStandardCompatibility.GetTypeCode( elementType ) ) #endif // !NETSTANDARD1_1 && !NETSTANDARD1_3 { case TypeCode.Boolean: case TypeCode.SByte: case TypeCode.Byte: { this.EmitStelem_I1(); break; } case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Char: { this.EmitStelem_I2(); break; } case TypeCode.Int32: case TypeCode.UInt32: { this.EmitStelem_I4(); break; } case TypeCode.Int64: case TypeCode.UInt64: { this.EmitStelem_I8(); break; } case TypeCode.Single: { this.EmitStelem_R4(); break; } case TypeCode.Double: { this.EmitStelem_R8(); break; } default: { // Other value type this.EmitLdelema( elementType ); elementLoadingEmitter( this ); this.EmitStobj( elementType ); break; } } }