private void SetMembers <T>(T targetObject) where T : class { var members = DeserializerContext.GetModelMembers(targetObject); foreach (var member in members) { if (member.IsRecordNumber) { member.SetMember(targetObject, Id); } else { string tpsFieldName = member.FieldAttribute.FieldName; TpsObject tpsFieldValue = GetRowValue(tpsFieldName, member.FieldAttribute.IsRequired); object tpsValue = member.FieldAttribute.InterpretValue(member.MemberInfo, tpsFieldValue); try { member.SetMember(targetObject, tpsValue); } catch (Exception ex) when(ex.GetType() != typeof(TpsParserException)) { throw new TpsParserException($"Cannot set member [{member}] to value '{tpsValue}' of type '{tpsValue.GetType()}' (Source value '{tpsFieldValue}' of {nameof(TpsObject)} type '{tpsFieldValue.GetType().Name}'). See the inner exception for details.", ex); } } } }
private void SetMembers <T>(T targetObject) { var members = typeof(T).GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (var member in members) { var tpsFieldAttr = member.GetCustomAttribute <TpsFieldAttribute>(); var tpsRecordNumberAttr = member.GetCustomAttribute <TpsRecordNumberAttribute>(); if (tpsFieldAttr != null && tpsRecordNumberAttr != null) { throw new TpsParserException($"Members cannot be marked with both {nameof(TpsFieldAttribute)} and {nameof(TpsRecordNumberAttribute)}. Property name '{member.Name}'."); } if (tpsFieldAttr != null) { string tpsFieldName = tpsFieldAttr.FieldName; TpsObject tpsFieldValue = GetRowValue(tpsFieldName, tpsFieldAttr.IsRequired); object convertedTpsValue = ConvertValue(GetMemberType(member), tpsFieldValue); object stringyTpsValue = ApplyStringConversion(member, tpsFieldAttr, convertedTpsValue); object tpsValue = CoerceNullValue(stringyTpsValue, tpsFieldAttr.FallbackValue); SetMember(member, targetObject, tpsValue); } if (tpsRecordNumberAttr != null) { SetMember(member, targetObject, Id); } } }
internal override object InterpretValue(MemberInfo member, TpsObject sourceObject) { if (member == null) { throw new ArgumentNullException(nameof(member)); } Type memberType = GetMemberType(member); if (memberType != typeof(bool) && memberType != typeof(bool?)) { throw new TpsParserException($"{nameof(TpsBooleanFieldAttribute)} is only valid on members of type {typeof(bool)} ({member})."); } var tpsValue = sourceObject?.Value; if (TrueValue != Behavior.Default && FalseValue == Behavior.Default) { if (tpsValue is string tpsString && TrueValue is string trueString) { return(string.Equals(tpsString.Trim(), trueString, StringComparison.OrdinalIgnoreCase)); } else { return(AsBoolean(sourceObject) ?? FallbackValue); } }
internal virtual object InterpretValue(MemberInfo member, TpsObject sourceObject) { if (member == null) { throw new ArgumentNullException(nameof(member)); } Type memberType = GetMemberType(member); var interpretedValue = InterpretValuePrivate(memberType, sourceObject); return(CoerceFallback(interpretedValue)); }
internal override object InterpretValue(MemberInfo member, TpsObject sourceObject) { if (member == null) { throw new ArgumentNullException(nameof(member)); } Type memberType = GetMemberType(member); if (memberType != typeof(string)) { throw new TpsParserException($"{nameof(TpsStringFieldAttribute)} is only valid on members of type {typeof(string)} ({member})."); } object tpsValue = sourceObject?.Value; if (tpsValue is null) { return(FallbackValue); } else if (TrimEnd && tpsValue is string tpsStringValue) { return(tpsStringValue.TrimEnd()); } else { try { if (tpsValue.GetType().GetMethod("ToString", new Type[] { typeof(string) }) is var miStringParam && miStringParam != null) { return((string)miStringParam.Invoke(tpsValue, new string[] { StringFormat })); } else if (tpsValue.GetType().GetMethod("ToString", Type.EmptyTypes) is var miNoParams && miNoParams != null) { return((string)miNoParams.Invoke(tpsValue, null)); }
public void ShouldThrowWhenDeserializing(TpsObject tpsObject) { var row = BuildRow(1, ("Count", tpsObject)); Assert.Throws <TpsParserException>(() => row.Deserialize <LongModel>()); }
private static object InterpretValuePrivate(Type memberType, TpsObject sourceObject) { if (memberType == typeof(DateTime) || memberType == typeof(DateTime?)) { if (sourceObject is IConvertible <DateTime> dateTimeConvertible) { return(dateTimeConvertible.AsType()); } else { return(sourceObject?.Value); } } else if (memberType == typeof(TimeSpan) || memberType == typeof(TimeSpan?)) { if (sourceObject is IConvertible <TimeSpan> timeSpanConvertible) { return(timeSpanConvertible.AsType()); } else { return(sourceObject?.Value); } } else if (memberType == typeof(bool) || memberType == typeof(bool?)) { return(((IConvertible <bool>)sourceObject)?.AsType()); } else if (memberType == typeof(string)) { return(sourceObject?.ToString()); } else if (memberType == typeof(decimal) || memberType == typeof(decimal?)) { if (sourceObject is IConvertible <decimal> decimalConvertible) { return(decimalConvertible.AsType()); } else { return(sourceObject?.Value); } } else if (memberType == typeof(int) || memberType == typeof(int?) || memberType == typeof(short) || memberType == typeof(short?) || memberType == typeof(long) || memberType == typeof(long?) || memberType == typeof(sbyte) || memberType == typeof(sbyte?)) { if (sourceObject is TpsDecimal decimalSource) { decimal sourceValue = ((IConvertible <decimal>)decimalSource).AsType(); Type destType = Nullable.GetUnderlyingType(memberType) ?? memberType; // Convert will round to the nearest whole value, so we floor/ceiling the value to emulate behavior of an explicit cast. decimal value = sourceValue < 0 ? Math.Ceiling(sourceValue) : Math.Floor(sourceValue); return(Convert.ChangeType(value, destType)); } else { return(sourceObject?.Value); } } else if (memberType == typeof(uint) || memberType == typeof(uint?) || memberType == typeof(ushort) || memberType == typeof(ushort?) || memberType == typeof(ulong) || memberType == typeof(ulong?) || memberType == typeof(byte) || memberType == typeof(byte?)) { if (sourceObject is TpsDecimal decimalSource) { decimal sourceValue = ((IConvertible <decimal>)decimalSource).AsType(); Type destType = Nullable.GetUnderlyingType(memberType) ?? memberType; // Convert will round to the nearest whole value, so we floor the value to emulate the behavior of an explicit cast. // If the value is negative, we coerce it to zero. decimal value = sourceValue < 0 ? 0 : Math.Floor(sourceValue); return(Convert.ChangeType(value, destType)); } else { return(sourceObject?.Value); } } else { return(sourceObject?.Value); } }
private bool?AsBoolean(TpsObject sourceObject) => ((IConvertible <bool>)sourceObject)?.AsType();