Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto property definition alongside [DynamoDbIgnore] #1

Draft
wants to merge 4 commits into
base: use-interface-attributes
Choose a base branch
from

Conversation

devtekve
Copy link
Owner

As I mentioned on AllocZero#238, under Attribute Annotation Requirements in EfficientDynamoDb, this PR should allow basically a more seamless experience. It will automatically map properties that are derivates of the class that has the attribute.

This PR introduces two new attribute classes as part of our push for improving DynamoDb utilization: DynamoDbAutoPropertyAttribute and DynamoDbIgnoreAttribute.

Key Changes

Introduction of DynamoDbAutoPropertyAttribute

This attribute allows automatic mapping of the properties from a class or interface to DynamoDb attributes. It includes:

  • Properties of the parent class
  • Properties of the derived classes
  • Properties of the implemented interfaces

The properties are marked to be automatically mapped to DynamoDb attributes unless they are explicitly ignored.

namespace EfficientDynamoDb.Attributes
{
    [DynamoDbAutoProperty]
    public sealed class SampleEntity
    {
        public string AutoProp1 { get; set; }
        public int AutoProp2 { get; set; }
    }
} 

Is equivalent to

namespace EfficientDynamoDb.Attributes
{
    public sealed class SampleEntity
    {
        [DynamoDbProperty("AutoProp1")]
        public string AutoProp1 { get; set; }
        
        [DynamoDbProperty("AutoProp2")]
        public int AutoProp2 { get; set; }
    }
} 

With DynamoDbAutoPropertyAttribute, the properties are automatically treated as DynamoDb attributes

Introduction of DynamoDbIgnoreAttribute

This attribute can be used to mark unwanted properties, preventing them from being automatically mapped to DynamoDb attributes, even in classes carrying the DynamoDbAutoPropertyAttribute.

namespace EfficientDynamoDb.Attributes
{
    [DynamoDbAutoProperty]
    public sealed class SampleEntityIgnore
    {
       public string AutoProp1 { get; set; }
       
       [DynamoDbIgnore]
       public int AutoProp2 { get; set; }
    }
}

Is equivalent to

namespace EfficientDynamoDb.Attributes
{
    public sealed class SampleEntityIgnore
    {
       [DynamoDbProperty("AutoProp1")]
       public string AutoProp1 { get; set; }
       
       // Note no attribute, it won't be mapped
       public int AutoProp2 { get; set; }
    }
}

In the example above, AutoProp1 is automatically mapped to a DynamoDb attribute, while AutoProp2 is ignored.

The Precedence of DynamoDbPropertyAttribute over DynamoDbIgnoreAttribute

In the event that a property is marked using both the DynamoDbIgnoreAttribute and DynamoDbPropertyAttribute, the explicit nature of DynamoDbPropertyAttribute takes precedence. This allows an overriding feature, whereby a specific property, despite being explicitly ignored (e.g., at the interface), can still be stored if it's explicitly required using DynamoDbPropertyAttribute at the derived class level.

This feature allows more flexibility in dealing with attributes on both parent and child classes or interfaces. By specifying DynamoDbPropertyAttribute on a property, that property will be included in the mapping process to DynamoDb attributes, bypassing the DynamoDbIgnoreAttribute.

namespace EfficientDynamoDb.Attributes
{
    [DynamoDbAutoProperty]
    public interface SampleInterface
    {
       [DynamoDbIgnore]
       int InterfaceProp1 { get; set; }
       
       string InterfaceProp2 { get; set; }
       
       double InterfaceProp3 { get; set; }
    }
    
    public sealed class SampleEntity : SampleInterface
    {
       [DynamoDbProperty("InterfaceProp1")]
       public int InterfaceProp1 { get; set; }
       
       public string InterfaceProp2 { get; set; }
       
       [DynamoDbIgnore]
       public double InterfaceProp3 { get; set; }
    }
}
  • InterfaceProp1 is MAPPED and this is why:

    • Even though it is ignored in the SampleInterface interface using DynamoDbIgnoreAttribute, it is explicitly marked for mapping to DynamoDb in the SampleEntity using DynamoDbPropertyAttribute, which takes presedence.
  • InterfaceProp2 is MAPPED and this is why:

    • Due to the interface having DynamoDbAutoProperty and no explicit ignore is defined, it is naturally mapped to DynamoDb.
  • InterfaceProp3 is NOT MAPPED and this is why:

    • By being explicitly marked to be ignored in the SampleEntity using DynamoDbIgnoreAttribute, the DynamoDbAutoProperty from the interface (parent) doesn't have any effect.

devtekve added 4 commits May 10, 2024 19:40
Create `DynamoDbAutoPropertyAttribute` and `DynamoDbIgnoreAttribute` classes. The `DynamoDbAutoPropertyAttribute` marks that all properties from a class, its derivatives, and interfaces should be automatically mapped to DynamoDb attributes, unless explicitly ignored using `DynamoDbIgnoreAttribute`. A new code incorporated in `DdbClassInfo.cs` handles these attributes, ensuring only relevant properties are mapped to DynamoDb attributes. This update simplifies effective usage of DynamoDb.
This commit introduces a check for the DynamoDbAutoPropertyAttribute in the DdbClassInfo class. This is done for any available interface. If no auto property is set, the check will then also be applied to the current type. This provides more robust handling of attributes in DynamoDB classes.
Re-arranged the object property extraction logic in DdbClassInfo constructor to handle property attributes from base classes and interfaces in an efficient way. Introduced a helper method "GetBaseTypes" to recursively fetch the base types of a given class and utilized BindingFlags at class level.
Shifted the priority of certain attribute retrieval operations and included object's own attributes as part of the discovery process. This also includes extraction of the object's own properties before considering its base types properties. This provides a better ordering and improves efficiency in metadata processing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant