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