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