private static void EmitNilImplicationForPrimitive(TracingILGenerator il, SerializingMember member, LocalBuilder value, Label endOfDeserialization) { Label targetIfNotNull = il.DefineLabel("END_IF_NULL"); EmitCompareNull(il, value, targetIfNotNull); switch (member.Contract.NilImplication) { case NilImplication.MemberDefault: il.EmitBr(endOfDeserialization); break; case NilImplication.Null: if (member.Member.GetMemberValueType().GetIsValueType() && (Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)) { il.EmitLdstr(member.Contract.Name); il.EmitLdtoken(member.Member.GetMemberValueType()); il.EmitAnyCall(_Type.GetTypeFromHandle); il.EmitLdtoken(member.Member.DeclaringType); il.EmitAnyCall(_Type.GetTypeFromHandle); il.EmitAnyCall(SerializationExceptions.NewValueTypeCannotBeNull3Method); il.EmitThrow(); } break; case NilImplication.Prohibit: il.EmitLdstr(member.Contract.Name); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); break; } il.MarkLabel(targetIfNotNull); }
/// <summary> /// Serializes the members. /// </summary> /// <param name="context">The context.</param> /// <param name="membersToSerialize">The members to serialize.</param> protected virtual void SerializeMembers(ISerializationContext <TSerializationContext> context, List <MemberValue> membersToSerialize) { ApiCop.UpdateRule <InitializationApiCopRule>("SerializerBase.WarmupAtStartup", x => x.SetInitializationMode(InitializationMode.Lazy, GetType().GetSafeFullName(false))); if (membersToSerialize.Count == 0) { return; } using (GetCurrentSerializationScopeManager(context.Configuration)) { var serializerModifiers = SerializationManager.GetSerializerModifiers(context.ModelType); foreach (var member in membersToSerialize) { bool skipByModifiers = false; foreach (var serializerModifier in serializerModifiers) { if (serializerModifier.ShouldIgnoreMember(context, context.Model, member)) { skipByModifiers = true; break; } } if (skipByModifiers) { continue; } var memberSerializationEventArgs = new MemberSerializationEventArgs(context, member); SerializingMember.SafeInvoke(this, memberSerializationEventArgs); BeforeSerializeMember(context, member); foreach (var serializerModifier in serializerModifiers) { serializerModifier.SerializeMember(context, member); } if (ShouldSerializeUsingParseAndToString(member, true)) { var objectToStringValue = SerializeUsingObjectToString(context, member); if (!string.IsNullOrWhiteSpace(objectToStringValue)) { member.Value = objectToStringValue; } } SerializeMember(context, member); AfterSerializeMember(context, member); SerializedMember.SafeInvoke(this, memberSerializationEventArgs); } } }
/// <summary> /// Serializes the members. /// </summary> /// <param name="context">The context.</param> /// <param name="membersToSerialize">The members to serialize.</param> protected virtual void SerializeMembers(ISerializationContext <TSerializationContext> context, List <MemberValue> membersToSerialize) { ApiCop.UpdateRule <InitializationApiCopRule>("SerializerBase.WarmupAtStartup", x => x.SetInitializationMode(InitializationMode.Lazy, GetType().GetSafeFullName())); var scopeName = SerializationContextHelper.GetSerializationReferenceManagerScopeName(); using (ScopeManager <ISerializer> .GetScopeManager(scopeName, () => this)) { var serializerModifiers = SerializationManager.GetSerializerModifiers(context.ModelType); foreach (var member in membersToSerialize) { bool skipByModifiers = false; foreach (var serializerModifier in serializerModifiers) { if (serializerModifier.ShouldIgnoreMember(context, context.Model, member)) { skipByModifiers = true; break; } } if (skipByModifiers) { continue; } var memberSerializationEventArgs = new MemberSerializationEventArgs(context, member); SerializingMember.SafeInvoke(this, memberSerializationEventArgs); BeforeSerializeMember(context, member); foreach (var serializerModifier in serializerModifiers) { serializerModifier.SerializeMember(context, member); } SerializeMember(context, member); AfterSerializeMember(context, member); SerializedMember.SafeInvoke(this, memberSerializationEventArgs); } } }
private MemberSetter CreateMemberSetter(SerializingMember member) { var fieldInfo = member.Member as FieldInfo; if (fieldInfo != null) { return(delegate(ref object target, object memberValue) { fieldInfo.SetValue(target, memberValue); }); } else { var propertyInfo = member.Member as PropertyInfo; Contract.Assert(propertyInfo != null, member.ToString() + ":" + member.GetType()); var propertySetter = propertyInfo.GetSetMethod(); return(delegate(ref object target, object memberValue) { propertySetter.Invoke(target, new object[] { memberValue }); }); } // Expression.Lambda<MemberSetter>( // Expression.Assign( // Expression.PropertyOrField( // refTargetParameter, // m.Member.Name // ), // Expression.Call( // Metadata._UnpackHelpers.ConvertWithEnsuringNotNull_1Method.MakeGenericMethod(m.Member.GetMemberValueType()), // valueParameter, // Expression.Constant(m.Member.Name), // Expression.Call( // Using RuntimeTypeHandle to avoid WinRT expression tree issue. // null, // Metadata._Type.GetTypeFromHandle, // Expression.Constant(m.Member.DeclaringType.TypeHandle) // ) // ) // ), // refTargetParameter, // valueParameter //).Compile() }
protected override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { LocalVariableHolder localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(_Packer.PackArrayHeader); packerIL.EmitPop(); SerializingMember[] memberArray = entries; for (int i = 0; i < memberArray.Length; i++) { Action <TracingILGenerator> loadValueEmitter = null; SerializingMember member = memberArray[i]; if (member.Member == null) { packerIL.EmitAnyLdarg(1); packerIL.EmitAnyCall(_Packer.PackNull); packerIL.EmitPop(); } else { if (loadValueEmitter == null) { loadValueEmitter = delegate(TracingILGenerator il) { if (typeof(TObject).IsValueType) { il.EmitAnyLdarga(2); } else { il.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il, member.Member); }; } Emittion.EmitSerializeValue(emitter, packerIL, 1, member.Member.GetMemberValueType(), member.Member.Name, member.Contract.NilImplication, loadValueEmitter, localHolder); } } packerIL.EmitRet(); }
/// <summary> /// Serializes the members. /// </summary> /// <param name="context">The context.</param> /// <param name="membersToSerialize">The members to serialize.</param> protected virtual void SerializeMembers(ISerializationContext <TSerializationContext> context, List <MemberValue> membersToSerialize) { var serializerModifiers = SerializationManager.GetSerializerModifiers(context.ModelType); foreach (var member in membersToSerialize) { bool skipByModifiers = false; foreach (var serializerModifier in serializerModifiers) { if (serializerModifier.ShouldIgnoreMember(context, context.Model, member)) { skipByModifiers = true; break; } } if (skipByModifiers) { continue; } var memberSerializationEventArgs = new MemberSerializationEventArgs(context, member); SerializingMember.SafeInvoke(this, memberSerializationEventArgs); BeforeSerializeMember(context, member); foreach (var serializerModifier in serializerModifiers) { serializerModifier.SerializeMember(context, member); } SerializeMember(context, member); AfterSerializeMember(context, member); SerializedMember.SafeInvoke(this, memberSerializationEventArgs); } }
/// <summary> /// Starts member serialization by invoking all the right events. /// </summary> /// <param name="context">The serialization context.</param> /// <param name="member">The member that is about to be serialized.</param> /// <param name="serializerModifiers">The serializer modifiers.</param> protected bool StartMemberSerialization(ISerializationContext <TSerializationContextInfo> context, MemberValue member, ISerializerModifier[] serializerModifiers) { var skipByModifiers = false; foreach (var serializerModifier in serializerModifiers) { if (serializerModifier.ShouldIgnoreMember(context, context.Model, member)) { skipByModifiers = true; break; } } if (skipByModifiers) { return(false); } SerializingMember?.Invoke(this, new MemberSerializationEventArgs(context, member)); BeforeSerializeMember(context, member); foreach (var serializerModifier in serializerModifiers) { serializerModifier.SerializeMember(context, member); } if (ShouldSerializeUsingParseAndToString(member, true)) { var objectToStringValue = SerializeUsingObjectToString(context, member); if (!string.IsNullOrWhiteSpace(objectToStringValue)) { member.Value = objectToStringValue; } } return(true); }
private static Func <object, object> CreateMemberGetter(SerializingMember member) { Func <object, object> coreGetter; var fieldInfo = member.Member as FieldInfo; if (fieldInfo != null) { coreGetter = target => fieldInfo.GetValue(target); } else { var propertyInfo = member.Member as PropertyInfo; Contract.Assert(propertyInfo != null, member.ToString() + ":" + member.GetType()); var propertyGetterInfo = propertyInfo.GetGetMethod(); coreGetter = target => propertyGetterInfo.Invoke(target, new object[0]); } if (member.Contract.NilImplication == NilImplication.Prohibit) { var name = member.Contract.Name; return(target => { var gotten = coreGetter(target); if (gotten == null) { throw SerializationExceptions.NewNullIsProhibited(name); } return gotten; }); } else { return(coreGetter); } }
private static void EmitNilImplicationForPrimitive(TracingILGenerator il, SerializingMember member, LocalBuilder value, Label endOfDeserialization) { var endIf = il.DefineLabel("END_IF_NULL"); EmitCompareNull(il, value, endIf); switch (member.Contract.NilImplication) { case NilImplication.MemberDefault: { /* * if( value == null ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitBr(endOfDeserialization); break; } case NilImplication.Null: { // Throw exception for non-nullable value type. // Nop for nullables. if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { /* * if( value == null ) * { * throw SerializationEceptions.NewValueTypeCannotBeNull( "...", typeof( MEMBER ), typeof( TYPE ) ); * } */ il.EmitLdstr(member.Contract.Name); il.EmitLdtoken(member.Member.GetMemberValueType()); il.EmitAnyCall(Metadata._Type.GetTypeFromHandle); il.EmitLdtoken(member.Member.DeclaringType); il.EmitAnyCall(Metadata._Type.GetTypeFromHandle); il.EmitAnyCall(SerializationExceptions.NewValueTypeCannotBeNull3Method); il.EmitThrow(); } break; } case NilImplication.Prohibit: { /* * if( value == null ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitLdstr(member.Contract.Name); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); break; } } il.MarkLabel(endIf); }
private static void EmitNilImplicationForPrimitive( TracingILGenerator il, SerializingMember member, LocalBuilder value, Label endOfDeserialization ) { var endIf = il.DefineLabel( "END_IF_NULL" ); EmitCompareNull( il, value, endIf ); switch ( member.Contract.NilImplication ) { case NilImplication.MemberDefault: { /* * if( value == null ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitBr( endOfDeserialization ); break; } case NilImplication.Null: { // Throw exception for non-nullable value type. // Nop for nullables. if ( member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType( member.Member.GetMemberValueType() ) == null ) { /* * if( value == null ) * { * throw SerializationEceptions.NewValueTypeCannotBeNull( "...", typeof( MEMBER ), typeof( TYPE ) ); * } */ il.EmitLdstr( member.Contract.Name ); il.EmitLdtoken( member.Member.GetMemberValueType() ); il.EmitAnyCall( Metadata._Type.GetTypeFromHandle ); il.EmitLdtoken( member.Member.DeclaringType ); il.EmitAnyCall( Metadata._Type.GetTypeFromHandle ); il.EmitAnyCall( SerializationExceptions.NewValueTypeCannotBeNull3Method ); il.EmitThrow(); } break; } case NilImplication.Prohibit: { /* * if( value == null ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitLdstr( member.Contract.Name ); il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); il.EmitThrow(); break; } } il.MarkLabel( endIf ); }
/// <summary> /// Emits the deserialize value. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="value">The value local variable which stores unpacked value.</param> /// <param name="targetType">The type of deserialzing type.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="memberName">The name of the member.</param> /// <param name="endOfDeserialization">The end of deserialization label for nil implication.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> private static void EmitDeserializeValueCore( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, SerializingMember? member, string memberName, Label endOfDeserialization, LocalVariableHolder localHolder ) { var directUnpacking = Metadata._Unpacker.GetDirectReadMethod( value.LocalType ); if ( directUnpacking != null && ( member == null || !UnpackHelpers.IsReadOnlyAppendableCollectionMember( member.Value.Member ) ) ) { var isSuccess = localHolder.IsDeserializationSucceeded; il.EmitLdc_I4_0(); il.EmitAnyStloc( isSuccess ); il.BeginExceptionBlock(); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitAnyLdloca( value ); il.EmitAnyCall( directUnpacking ); il.EmitAnyStloc( isSuccess ); il.BeginCatchBlock( typeof( MessageTypeException ) ); var ex = localHolder.GetCatchedException( typeof( MessageTypeException ) ); il.EmitAnyStloc( ex ); il.EmitTypeOf( targetType ); il.EmitLdstr( memberName ); il.EmitAnyLdloc( ex ); il.EmitAnyCall( SerializationExceptions.NewFailedToDeserializeMemberMethod ); il.EmitThrow(); il.EndExceptionBlock(); var endIf0 = il.DefineLabel( "END_IF" ); il.EmitAnyLdloc( isSuccess ); il.EmitBrtrue_S( endIf0 ); il.EmitAnyCall( SerializationExceptions.NewUnexpectedEndOfStreamMethod ); il.EmitThrow(); il.MarkLabel( endIf0 ); if ( member != null ) { // If null, nil implication is NOT needed. EmitNilImplicationForPrimitive( il, member.Value, value, endOfDeserialization ); } } else { EmitGeneralRead( il, unpackerArgumentIndex ); if ( member != null ) { // If null, nil implication is NOT needed. EmitNilImplication( il, unpackerArgumentIndex, member.Value.Contract.Name, member.Value.Contract.NilImplication, endOfDeserialization, localHolder ); } var thenIffCollection = il.DefineLabel( "THEN_IF_COLLECTION" ); var endIfCollection = il.DefineLabel( "END_IF_COLLECTION" ); /* * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * value = GET_SERIALIZER().UnpackFrom( unpacker ); * } * else * { * using( var subtreeUnpacker = unpacker.ReadSubtree() ) * { * value = GET_SERIALIZER().UnpackFrom( subtreeUnpacker ); * } * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsArrayHeader ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsMapHeader ); il.EmitOr(); il.EmitBrtrue_S( thenIffCollection ); EmitUnpackFrom( emitter, il, value, unpackerArgumentIndex ); il.EmitBr_S( endIfCollection ); var subtreeUnpacker = localHolder.SubtreeUnpacker; il.MarkLabel( thenIffCollection ); EmitUnpackerBeginReadSubtree( il, unpackerArgumentIndex, subtreeUnpacker ); EmitUnpackFrom( emitter, il, value, subtreeUnpacker ); EmitUnpackerEndReadSubtree( il, subtreeUnpacker ); il.MarkLabel( endIfCollection ); } }
/// <summary> /// Emits the deserialize value. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="result">The result local variable which represents the result of deserialization.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValue( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder ) { Contract.Requires( emitter != null ); Contract.Requires( il != null ); Contract.Requires( unpackerArgumentIndex >= 0 ); Contract.Requires( result != null ); var endOfDeserialization = il.DefineLabel( "END_OF_DESERIALIZATION" ); /* * * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * valueN = GET_SERIALIZER.UnpackFrom( unpacker ); * } * else * { * using( var subtreeUnpacker = unpacker.ReadSubtree ) * { * valueN = GET_SERIALIZER.UnpackFrom( unpacker ); * } * } * * isValueNUnpacked = true; * END_OF_DESERIALIZATION: */ LocalBuilder value; bool useDummyNullableValue = false; if ( member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType( member.Member.GetMemberValueType() ) == null ) { // Use temporary nullable value for nil implication. value = localHolder.GetDeserializedValue( typeof( Nullable<> ).MakeGenericType( member.Member.GetMemberValueType() ) ); useDummyNullableValue = true; } else { value = localHolder.GetDeserializedValue( member.Member.GetMemberValueType() ); } if ( value.LocalType.GetIsValueType() ) { il.EmitAnyLdloca( value ); il.EmitInitobj( value.LocalType ); } else { il.EmitLdnull(); il.EmitAnyStloc( value ); } EmitDeserializeValueCore( emitter, il, unpackerArgumentIndex, value, result.LocalType, member, member.Contract.Name, endOfDeserialization, localHolder ); if ( result.LocalType.IsValueType ) { il.EmitAnyLdloca( result ); } else { il.EmitAnyLdloc( result ); } if ( useDummyNullableValue ) { il.EmitAnyLdloca( value ); il.EmitGetProperty( typeof( Nullable<> ).MakeGenericType( member.Member.GetMemberValueType() ).GetProperty( "Value" ) ); } else { il.EmitAnyLdloc( value ); } EmitStoreValue( il, member.Member ); il.MarkLabel( endOfDeserialization ); }
/// <summary> /// Emits the nil implication. /// </summary> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="member">Metadata of the serializing member.</param> /// <param name="endOfDeserialization">The label to the end of deserialization.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitNilImplication( TracingILGenerator il, int unpackerArgumentIndex, SerializingMember member, Label endOfDeserialization, LocalVariableHolder localHolder ) { switch ( member.Contract.NilImplication ) { case NilImplication.MemberDefault: { // TODO: This should be empty for extra items. /* * if( unpacker.Data.Value.IsNil ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.LastReadData ); var data = localHolder.UnpackedData; il.EmitAnyStloc( data ); il.EmitAnyLdloca( data ); il.EmitGetProperty( Metadata._MessagePackObject.IsNil ); il.EmitBrtrue( endOfDeserialization ); break; } case NilImplication.Null: { if ( member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType( member.Member.GetMemberValueType() ) == null ) { throw SerializationExceptions.NewValueTypeCannotBeNull( member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType ); } if ( !member.Member.CanSetValue() ) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull( member.Contract.Name ); } break; } case NilImplication.Prohibit: { if ( !member.Member.CanSetValue() ) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull( member.Contract.Name ); } /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.LastReadData ); var data = localHolder.UnpackedData; il.EmitAnyStloc( data ); il.EmitAnyLdloca( data ); il.EmitGetProperty( Metadata._MessagePackObject.IsNil ); var endIf0 = il.DefineLabel( "END_IF0" ); il.EmitBrfalse_S( endIf0 ); il.EmitLdstr( member.Contract.Name ); il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); il.EmitThrow(); il.MarkLabel( endIf0 ); break; } } }
public static void EmitDeserializeValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder) { LocalBuilder deserializedValue; Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(result != null); Label endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); bool flag = false; if (member.Member.GetMemberValueType().GetIsValueType() && (Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)) { deserializedValue = localHolder.GetDeserializedValue(typeof(Nullable <>).MakeGenericType(new Type[] { member.Member.GetMemberValueType() })); flag = true; } else { deserializedValue = localHolder.GetDeserializedValue(member.Member.GetMemberValueType()); } if (deserializedValue.LocalType.GetIsValueType()) { il.EmitAnyLdloca(deserializedValue); il.EmitInitobj(deserializedValue.LocalType); } else { il.EmitLdnull(); il.EmitAnyStloc(deserializedValue); } EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, deserializedValue, result.LocalType, new SerializingMember?(member), member.Contract.Name, endOfDeserialization, localHolder); if (result.LocalType.IsValueType) { il.EmitAnyLdloca(result); } else { il.EmitAnyLdloc(result); } if (flag) { il.EmitAnyLdloca(deserializedValue); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(new Type[] { member.Member.GetMemberValueType() }).GetProperty("Value")); } else { il.EmitAnyLdloc(deserializedValue); } EmitStoreValue(il, member.Member); il.MarkLabel(endOfDeserialization); }
protected ObjectReflectionMessagePackSerializer(Type type, SerializationContext context, SerializingMember[] members) : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions) { if (type.GetIsAbstract() || type.GetIsInterface()) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); } this._createInstance = () => Activator.CreateInstance(type); //Expression.Lambda<Func<T>>( // typeof(T).GetIsValueType() // ? Expression.Default(typeof(T)) as Expression // : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes)) // ).Compile(); var isPackable = typeof(IPackable).IsAssignableFrom(type); var isUnpackable = typeof(IUnpackable).IsAssignableFrom(type); if (isPackable && isUnpackable) { this._memberSerializers = null; this._indexMap = null; this._isCollection = null; this._nilImplications = null; this._memberNames = null; } else { this._memberSerializers = members.Select( m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray ( ); this._indexMap = members .Select((m, i) => new KeyValuePair<SerializingMember, int>(m, i)) .Where(kv => kv.Key.Member != null) .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value); this._isCollection = members.Select( m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()). Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray(); // NilImplication validity check foreach (var member in members) { switch (member.Contract.NilImplication) { case NilImplication.Null: { if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { throw SerializationExceptions.NewValueTypeCannotBeNull( member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType ); } if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name); } break; } } } this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray(); this._memberNames = members.Select(m => m.Contract.Name).ToArray(); } if (isPackable) { this._packToMessage = (target, packer, packingOptions) => { ((IPackable)target).PackToMessage(packer, packingOptions); //typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single().Invoke(target, new object[] { packer, packingOptions }); }; this._memberGetters = null; } else { this._packToMessage = null; this._memberGetters = members.Select<SerializingMember,Func<object,object>>( m => m.Member == null ? (target => null) : CreateMemberGetter(m)).ToArray(); } if (isUnpackable) { this._unpackFromMessage = delegate(ref object target, Unpacker value) { ((IUnpackable)target).UnpackFromMessage(value); }; this._memberSetters = null; } else { this._unpackFromMessage = null; this._memberSetters = members.Select( m => m.Member == null ? delegate(ref object target, object memberValue) { } : m.Member.CanSetValue() ? CreateMemberSetter(m) : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member) ? default(MemberSetter) : ThrowGetOnlyMemberIsInvalid(m.Member) ).ToArray(); } }
private MemberSetter CreateMemberSetter(SerializingMember member) { var fieldInfo = member.Member as FieldInfo; if (fieldInfo != null) { return delegate(ref object target, object memberValue) { fieldInfo.SetValue(target, memberValue); }; } else { var propertyInfo = member.Member as PropertyInfo; Contract.Assert(propertyInfo != null, member.ToString() + ":" + member.GetType()); var propertySetter = propertyInfo.GetSetMethod(); return delegate(ref object target, object memberValue) { propertySetter.Invoke(target, new object[] { memberValue }); }; } // Expression.Lambda<MemberSetter>( // Expression.Assign( // Expression.PropertyOrField( // refTargetParameter, // m.Member.Name // ), // Expression.Call( // Metadata._UnpackHelpers.ConvertWithEnsuringNotNull_1Method.MakeGenericMethod(m.Member.GetMemberValueType()), // valueParameter, // Expression.Constant(m.Member.Name), // Expression.Call( // Using RuntimeTypeHandle to avoid WinRT expression tree issue. // null, // Metadata._Type.GetTypeFromHandle, // Expression.Constant(m.Member.DeclaringType.TypeHandle) // ) // ) // ), // refTargetParameter, // valueParameter //).Compile() }
private static Func<object, object> CreateMemberGetter(SerializingMember member) { Func<object, object> coreGetter; var fieldInfo = member.Member as FieldInfo; if (fieldInfo != null) { coreGetter = target => fieldInfo.GetValue(target); } else { var propertyInfo = member.Member as PropertyInfo; Contract.Assert(propertyInfo != null, member.ToString() + ":" + member.GetType()); var propertyGetterInfo = propertyInfo.GetGetMethod(); coreGetter = target => propertyGetterInfo.Invoke(target, new object[0]); } if (member.Contract.NilImplication == NilImplication.Prohibit) { var name = member.Contract.Name; return target => { var gotten = coreGetter(target); if (gotten == null) { throw SerializationExceptions.NewNullIsProhibited(name); } return gotten; }; } else { return coreGetter; } }
private static Func <T, object> CreateMemberGetter(ParameterExpression targetParameter, SerializingMember member) { var coreGetter = Expression.Lambda <Func <T, object> >( Expression.Convert( Expression.PropertyOrField( targetParameter, member.Member.Name ), typeof(object) ), targetParameter ).Compile(); if (member.Contract.NilImplication == NilImplication.Prohibit) { var name = member.Contract.Name; return(target => { var gotten = coreGetter(target); if (gotten == null) { throw SerializationExceptions.NewNullIsProhibited(name); } return gotten; }); } else { return(coreGetter); } }
/// <summary> /// Emits the deserialize value. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="result">The result local variable which represents the result of deserialization.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(result != null); var endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); /* * * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * valueN = GET_SERIALIZER.UnpackFrom( unpacker ); * } * else * { * using( var subtreeUnpacker = unpacker.ReadSubtree ) * { * valueN = GET_SERIALIZER.UnpackFrom( unpacker ); * } * } * * isValueNUnpacked = true; * END_OF_DESERIALIZATION: */ LocalBuilder value; bool useDummyNullableValue = false; if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { // Use temporary nullable value for nil implication. value = localHolder.GetDeserializedValue( typeof(Nullable <>).MakeGenericType(member.Member.GetMemberValueType())); useDummyNullableValue = true; } else { value = localHolder.GetDeserializedValue(member.Member.GetMemberValueType()); } if (value.LocalType.GetIsValueType()) { il.EmitAnyLdloca(value); il.EmitInitobj(value.LocalType); } else { il.EmitLdnull(); il.EmitAnyStloc(value); } EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, result.LocalType, member, member.Contract.Name, endOfDeserialization, localHolder); if (result.LocalType.IsValueType) { il.EmitAnyLdloca(result); } else { il.EmitAnyLdloc(result); } if (useDummyNullableValue) { il.EmitAnyLdloca(value); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(member.Member.GetMemberValueType()).GetProperty("Value")); } else { il.EmitAnyLdloc(value); } EmitStoreValue(il, member.Member); il.MarkLabel(endOfDeserialization); }
/// <summary> /// Emits the nil implication. /// </summary> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="member">Metadata of the serializing member.</param> /// <param name="endOfDeserialization">The label to the end of deserialization.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitNilImplication( TracingILGenerator il, int unpackerArgumentIndex, SerializingMember member, Label endOfDeserialization, LocalVariableHolder localHolder ) { switch (member.Contract.NilImplication) { case NilImplication.MemberDefault: { // TODO: This should be empty for extra items. /* * if( unpacker.Data.Value.IsNil ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.LastReadData); var data = localHolder.UnpackedData; il.EmitAnyStloc(data); il.EmitAnyLdloca(data); il.EmitGetProperty(Metadata._MessagePackObject.IsNil); il.EmitBrtrue(endOfDeserialization); break; } case NilImplication.Null: { if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { throw SerializationExceptions.NewValueTypeCannotBeNull( member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType ); } if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull( member.Contract.Name ); } break; } case NilImplication.Prohibit: { if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull( member.Contract.Name ); } /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.LastReadData); var data = localHolder.UnpackedData; il.EmitAnyStloc(data); il.EmitAnyLdloca(data); il.EmitGetProperty(Metadata._MessagePackObject.IsNil); var endIf0 = il.DefineLabel("END_IF0"); il.EmitBrfalse_S(endIf0); il.EmitLdstr(member.Contract.Name); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(endIf0); break; } } }
public ArrayFormatObjectRecflectionMessagePackSerializer(Type type, SerializationContext context, SerializingMember[] members) : base(type, context, members) { }