private bool TryFromMap(Type targetType, Document map, DynamoDBFlatConfig flatConfig, out object output) { output = null; if (!Utils.CanInstantiate(targetType)) { return(false); } Type valueType; if (!IsSupportedDictionaryType(targetType, out valueType)) { return(false); } var dictionary = Utils.Instantiate(targetType); var idictionary = dictionary as IDictionary; var propertyStorage = new SimplePropertyStorage(valueType); foreach (var kvp in map) { var key = kvp.Key; var entry = kvp.Value; var item = FromDynamoDBEntry(propertyStorage, entry, flatConfig); idictionary.Add(key, item); } output = dictionary; return(true); }
/// <summary> /// Validates configurations and sets required fields /// </summary> public void Validate() { if (IsVersion) { Utils.ValidateVersionType(MemberType); // no conversion is possible, so type must be a nullable primitive } if (IsHashKey && IsRangeKey) { throw new InvalidOperationException("Property " + PropertyName + " cannot be both hash and range key"); } if (IsKey || IsGSIKey) { if (Converter == null && !Utils.IsPrimitive(MemberType)) { throw new InvalidOperationException("Key " + PropertyName + " must be of primitive type"); } } foreach (var index in Indexes) { IndexNames.AddRange(index.IndexNames); } if (ConverterType != null) { if (!Utils.CanInstantiate(ConverterType) || !Utils.ImplementsInterface(ConverterType, typeof(IPropertyConverter))) { throw new InvalidOperationException("Converter for " + PropertyName + " must be instantiable with no parameters and must implement IPropertyConverter"); } this.Converter = Utils.Instantiate(ConverterType) as IPropertyConverter; } }
// PrimitiveList <--> List private static bool TryFromPrimitiveList(Type targetType, PrimitiveList value, out object output) { var targetTypeWrapper = TypeFactory.GetTypeInfo(targetType); Type elementType; if ((!Utils.ImplementsInterface(targetType, typeof(ICollection <>)) && !Utils.ImplementsInterface(targetType, typeof(IList))) || !Utils.CanInstantiate(targetType) || !Utils.IsPrimitive(elementType = targetTypeWrapper.GetGenericArguments()[0])) { output = null; return(false); } var collection = Utils.Instantiate(targetType); IList ilist = collection as IList; bool useIListInterface = ilist != null; MethodInfo collectionAdd = null; if (!useIListInterface) { collectionAdd = targetTypeWrapper.GetMethod("Add"); } foreach (Primitive primitive in value.Entries) { object primitiveValue; if (TryFromPrimitive(elementType, primitive, out primitiveValue)) { if (useIListInterface) { ilist.Add(primitiveValue); } else { collectionAdd.Invoke(collection, new object[] { primitiveValue }); } } else { output = null; return(false); } } output = collection; return(true); }
private bool TryFromList(Type targetType, DynamoDBList list, DynamoDBFlatConfig flatConfig, out object output) { var targetTypeWrapper = TypeFactory.GetTypeInfo(targetType); if ((!Utils.ImplementsInterface(targetType, typeof(ICollection <>)) && !Utils.ImplementsInterface(targetType, typeof(IList))) || !Utils.CanInstantiate(targetType)) { output = null; return(false); } var elementType = targetTypeWrapper.GetGenericArguments()[0]; var collection = Utils.Instantiate(targetType); IList ilist = collection as IList; bool useIListInterface = ilist != null; var propertyStorage = new SimplePropertyStorage(elementType); MethodInfo collectionAdd = null; if (!useIListInterface) { collectionAdd = targetTypeWrapper.GetMethod("Add"); } foreach (DynamoDBEntry entry in list.Entries) { var item = FromDynamoDBEntry(propertyStorage, entry, flatConfig); if (useIListInterface) { ilist.Add(item); } else { collectionAdd.Invoke(collection, new object[] { item }); } } output = collection; return(true); }
// constructor public StorageConfig(ITypeInfo targetTypeInfo) { var type = targetTypeInfo.Type; if (!Utils.CanInstantiate(type)) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type {0} is unsupported, it cannot be instantiated", targetTypeInfo.FullName)); } TargetTypeInfo = targetTypeInfo; Properties = new List <PropertyStorage>(); PropertyToPropertyStorageMapping = new Dictionary <string, PropertyStorage>(StringComparer.Ordinal); TargetTypeMembers = GetMembersDictionary(targetTypeInfo); if (TargetTypeMembers.Count == 0) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type {0} is unsupported, it has no supported members", targetTypeInfo.FullName)); } }
internal static ItemStorageConfig CreateStorageConfig(Type type) { if (type == null) { throw new ArgumentNullException("type"); } var typeWrapper = TypeFactory.GetTypeInfo(type); ItemStorageConfig config = new ItemStorageConfig(type); DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(type); if (tableAttribute == null || string.IsNullOrEmpty(tableAttribute.TableName)) { throw new InvalidOperationException("No DynamoDBTableAttribute on type"); } if (string.IsNullOrEmpty(tableAttribute.TableName)) { throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null"); } config.TableName = tableAttribute.TableName; config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties; foreach (var member in typeWrapper.GetMembers()) { // filter out non-fields and non-properties if (!(member is FieldInfo || member is PropertyInfo)) { continue; } // filter out properties that aren't both read and write if (!Utils.IsReadWrite(member)) { continue; } // prepare basic info Type memberType = Utils.GetType(member); string attributeName = GetAccurateCase(config, member.Name); string propertyName = member.Name; PropertyStorage propertyStorage = new PropertyStorage(member, memberType); // run through all DDB attributes bool ignorePresent = false; var allAttributes = Utils.GetAttributes(member); foreach (var attribute in allAttributes) { // filter out ignored properties if (attribute is DynamoDBIgnoreAttribute) { ignorePresent |= true; } // if ignore attribute is present, ignore other attributes if (ignorePresent) { continue; } if (attribute is DynamoDBVersionAttribute) { Utils.ValidateVersionType(memberType); // no conversion is possible, so type must be a nullable primitive propertyStorage.IsVersion = true; } DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute; if (propertyAttribute != null) { if (!string.IsNullOrEmpty(propertyAttribute.AttributeName)) { attributeName = GetAccurateCase(config, propertyAttribute.AttributeName); } if (propertyAttribute is DynamoDBHashKeyAttribute) { if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType)) { throw new InvalidOperationException("Hash key " + propertyName + " must be of primitive type"); } var gsiHashAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexHashKeyAttribute; if (gsiHashAttribute != null) { propertyStorage.IsGSIHashKey = true; if (gsiHashAttribute.IndexNames == null || gsiHashAttribute.IndexNames.Length == 0) { throw new InvalidOperationException("Global Secondary Index must not be null or empty"); } propertyStorage.Indexes.AddRange(gsiHashAttribute.IndexNames); AddGSIConfigs(config, gsiHashAttribute.IndexNames, propertyName, true); } else { propertyStorage.IsHashKey = true; } } if (propertyAttribute is DynamoDBRangeKeyAttribute) { if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType)) { throw new InvalidOperationException("Range key " + propertyName + " must be of primitive type"); } var gsiRangeAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexRangeKeyAttribute; if (gsiRangeAttribute != null) { propertyStorage.IsGSIRangeKey = true; if (gsiRangeAttribute.IndexNames == null || gsiRangeAttribute.IndexNames.Length == 0) { throw new InvalidOperationException("Global Secondary Index must not be null or empty"); } propertyStorage.Indexes.AddRange(gsiRangeAttribute.IndexNames); AddGSIConfigs(config, gsiRangeAttribute.IndexNames, propertyName, false); } else { propertyStorage.IsRangeKey = true; } } DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute; if (lsiRangeKeyAttribute != null) { if (lsiRangeKeyAttribute.IndexNames == null || lsiRangeKeyAttribute.IndexNames.Length == 0) { throw new InvalidOperationException("Local Secondary Index must not be null or empty"); } propertyStorage.Indexes.AddRange(lsiRangeKeyAttribute.IndexNames); propertyStorage.IsLSIRangeKey = true; foreach (var index in lsiRangeKeyAttribute.IndexNames) { List <string> properties; if (!config.IndexNameToLSIRangePropertiesMapping.TryGetValue(index, out properties)) { properties = new List <string>(); config.IndexNameToLSIRangePropertiesMapping[index] = properties; } properties.Add(propertyName); } } if (propertyAttribute.Converter != null) { if (!Utils.CanInstantiate(propertyAttribute.Converter) || !Utils.ImplementsInterface(propertyAttribute.Converter, typeof(IPropertyConverter))) { throw new InvalidOperationException("Converter for " + propertyName + " must be instantiable with no parameters and must implement IPropertyConverter"); } propertyStorage.Converter = Utils.Instantiate(propertyAttribute.Converter) as IPropertyConverter; } } } propertyStorage.PropertyName = propertyName; propertyStorage.AttributeName = attributeName; // only add property storage if no ignore attribute was present if (!ignorePresent) { config.AddPropertyStorage(propertyStorage); } } if (config.HashKeyPropertyNames.Count == 0) { throw new InvalidOperationException("No hash key configured for type " + type.FullName); } return(config); }
internal static ItemStorageConfig CreateStorageConfig(Type type) { if (type == null) { throw new ArgumentNullException("type"); } ItemStorageConfig config = new ItemStorageConfig(type); DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(type); if (tableAttribute == null || string.IsNullOrEmpty(tableAttribute.TableName)) { throw new InvalidOperationException("No DynamoDBTableAttribute on type"); } if (string.IsNullOrEmpty(tableAttribute.TableName)) { throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null"); } config.TableName = tableAttribute.TableName; config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties; foreach (var member in type.GetMembers()) { // filter out non-fields and non-properties if (!(member is FieldInfo || member is PropertyInfo)) { continue; } // filter out properties that aren't both read and write if (!Utils.IsReadWrite(member)) { continue; } DynamoDBAttribute attribute = Utils.GetAttribute(member); // filter out ignored properties if (attribute is DynamoDBIgnoreAttribute) { continue; } Type memberType = Utils.GetType(member); string attributeName = GetAccurateCase(config, member.Name); string propertyName = member.Name; PropertyStorage propertyStorage = new PropertyStorage { Member = member, MemberType = memberType, }; if (attribute is DynamoDBVersionAttribute) { Utils.ValidateVersionType(memberType); // no conversion is possible, so type must be a nullable primitive propertyStorage.IsVersion = true; } DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute; if (propertyAttribute != null) { if (!string.IsNullOrEmpty(propertyAttribute.AttributeName)) { attributeName = GetAccurateCase(config, propertyAttribute.AttributeName); } if (propertyAttribute is DynamoDBHashKeyAttribute) { if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType)) { throw new InvalidOperationException("Hash key " + propertyName + " must be of primitive type"); } propertyStorage.IsHashKey = true; } if (propertyAttribute is DynamoDBRangeKeyAttribute) { if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType)) { throw new InvalidOperationException("Range key " + propertyName + " must be of primitive type"); } propertyStorage.IsRangeKey = true; } if (propertyAttribute is DynamoDBLocalSecondaryIndexRangeKeyAttribute) { DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute; if (lsiRangeKeyAttribute.IndexNames == null || lsiRangeKeyAttribute.IndexNames.Length == 0) { throw new InvalidOperationException("Local Secondary Index must not be null or empty"); } propertyStorage.Indexes.AddRange(lsiRangeKeyAttribute.IndexNames); } if (propertyAttribute.Converter != null) { if (!Utils.CanInstantiate(propertyAttribute.Converter) || !Utils.ImplementsInterface(propertyAttribute.Converter, typeof(IPropertyConverter))) { throw new InvalidOperationException("Converter for " + propertyName + " must be instantiable with no parameters and must implement IPropertyConverter"); } propertyStorage.Converter = Utils.Instantiate(propertyAttribute.Converter) as IPropertyConverter; } } propertyStorage.PropertyName = propertyName; propertyStorage.AttributeName = attributeName; config.AddPropertyStorage(propertyStorage); } if (config.HashKeyPropertyNames.Count == 0) { throw new InvalidOperationException("No hash key configured for type " + type.FullName); } return(config); }