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;
				}
			}
		}