/// <summary> /// The <see cref="FromMap(Dictionary{string,AttributeValue},Type,DynamoSerializerOptions)"/> method converts a DynamoDB M attribute value to the type of the converter. /// </summary> /// <param name="value">The DynamoDB attribute value to convert.</param> /// <param name="targetType">The expected return type.</param> /// <param name="options">The deserialization options.</param> /// <returns>An instance of type <paramref name="targetType"/>.</returns> public override object?FromMap(Dictionary <string, AttributeValue> value, Type targetType, DynamoSerializerOptions options) { // create instance and set properties on it var result = Activator.CreateInstance(targetType) ?? throw new ApplicationException("Activator.CreateInstance() returned null"); foreach (var property in targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) { var propertyAttributes = property.GetCustomAttributes(); // check if this object property should be ignored if (!(propertyAttributes.OfType <DynamoPropertyIgnoreAttribute>().SingleOrDefault() is null)) { continue; } // check if this object property has a custom name var name = propertyAttributes.OfType <DynamoPropertyNameAttribute>().SingleOrDefault()?.Name ?? property.Name; if (value.TryGetValue(name, out var attribute)) { property.SetValue(result, DynamoSerializer.Deserialize(attribute, property.PropertyType, options)); } else { property.SetValue(result, DynamoSerializer.Deserialize(attribute: null, property.PropertyType, options)); } } return(result); }
/// <summary> /// The <see cref="FromMap(Dictionary{string,AttributeValue},Type,DynamoSerializerOptions)"/> method converts a DynamoDB M attribute value to the type of the converter. /// </summary> /// <param name="value">The DynamoDB attribute value to convert.</param> /// <param name="targetType">The expected return type.</param> /// <param name="options">The deserialization options.</param> /// <returns>An instance of type <paramref name="targetType"/>.</returns> public override object?FromMap(Dictionary <string, AttributeValue> value, Type targetType, DynamoSerializerOptions options) { if (targetType.IsAssignableFrom(typeof(Dictionary <string, object>))) { return(value.ToDictionary(kv => kv.Key, kv => DynamoSerializer.Deserialize(kv.Value, typeof(object), options))); } // check if item type can be determined via `IDictionary<string, T>` inheritance var itemType = GetDictionaryItemType(targetType); // determine if a concrete type needs to be identified Type mapType = targetType; if (targetType.IsInterface) { if (!(itemType is null)) { mapType = typeof(Dictionary <,>).MakeGenericType(new[] { typeof(string), itemType }); } else { mapType = typeof(Dictionary <string, object>); } if (targetType.IsAssignableFrom(mapType)) { throw new DynamoSerializationException($"incompatible target type for M attribute value (given: {targetType.FullName})"); } }
/// <summary> /// The <see cref="FromList(List{AttributeValue},Type,DynamoSerializerOptions)"/> method converts a DynamoDB L attribute value to the type of the converter. /// </summary> /// <param name="value">The DynamoDB attribute value to convert.</param> /// <param name="targetType">The expected return type.</param> /// <param name="options">The deserialization options.</param> /// <returns>An instance of type <paramref name="targetType"/>.</returns> public override object?FromList(List <AttributeValue> value, Type targetType, DynamoSerializerOptions options) { if (targetType.IsAssignableFrom(typeof(List <object>))) { // NOTE (2021-06-23, bjorg): this covers the case where targetype is `IList` // return List<object> return(value.Select(item => DynamoSerializer.Deserialize(item, targetType: null, options)).ToList()); } // check if item type can be determined via `IList<T>` inheritance var itemType = GetListItemType(targetType); // determine if a concrete type needs to be identified Type listType = targetType; if (targetType.IsInterface) { if (itemType != null) { // create `List<T>` listType = typeof(List <>).MakeGenericType(new[] { itemType }); } else { // create `ArrayList` listType = typeof(ArrayList); } if (!targetType.IsAssignableFrom(listType)) { throw new DynamoSerializationException($"incompatible target type for L attribute value (given: {targetType.FullName})"); } } // check if we can use the `IList` interface to add items to the list instance if (typeof(IList).IsAssignableFrom(listType)) { var result = (IList)(Activator.CreateInstance(listType) ?? throw new ApplicationException("Activator.CreateInstance() returned null")); foreach (var item in value) { result.Add(DynamoSerializer.Deserialize(item, itemType, options)); } return(result); } else { // use `dynamic` to invoke the appropriate typed `Add()` method dynamic result = Activator.CreateInstance(listType) ?? throw new ApplicationException("Activator.CreateInstance() returned null"); foreach (var item in value) { result.Add(DynamoSerializer.Deserialize(item, itemType, options)); } return(result); } }
private object?DeserializeItem(Dictionary <string, AttributeValue> item, Type?type) => DynamoSerializer.Deserialize(item, type, SerializerOptions);
internal TRecord?DeserializeItem <TRecord>(Dictionary <string, AttributeValue> item) where TRecord : class => DynamoSerializer.Deserialize <TRecord>(item, SerializerOptions);