From 091e1f7dd6ec0d53e8d611551b24b04ca21eb5ac Mon Sep 17 00:00:00 2001 From: petero-dk <2478689+petero-dk@users.noreply.github.com> Date: Mon, 27 Nov 2023 20:19:52 +0100 Subject: [PATCH] Implement string enum storage via attributes --- .../ITS025StoreEnum.cs | 58 +++++++++++++++++++ .../Models/UserModel4.cs | 29 ++++++++++ .../Attributes/StoreEnumAsStringAttribute.cs | 53 +++++++++++++++++ README.md | 23 ++++++++ 4 files changed, 163 insertions(+) create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs create mode 100644 CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs create mode 100644 CoreHelpers.WindowsAzure.Storage.Table/Attributes/StoreEnumAsStringAttribute.cs diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs b/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs new file mode 100644 index 0000000..58bcb4d --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS025StoreEnum.cs @@ -0,0 +1,58 @@ +using System; +using CoreHelpers.WindowsAzure.Storage.Table.Tests.Contracts; +using CoreHelpers.WindowsAzure.Storage.Table.Tests.Extensions; +using CoreHelpers.WindowsAzure.Storage.Table.Tests.Models; +using Xunit.DependencyInjection; + +namespace CoreHelpers.WindowsAzure.Storage.Table.Tests +{ + [Startup(typeof(Startup))] + [Collection("Sequential")] + public class ITS025StoreEnum + { + private readonly IStorageContext _rootContext; + + public ITS025StoreEnum(IStorageContext context) + { + _rootContext = context; + } + + [Fact] + public async Task VerifyAttributeMapper() + { + using (var storageContext = _rootContext.CreateChildContext()) + { + // set the tablename context + storageContext.SetTableContext(); + + // create a new user + var user = new UserModel4() { FirstName = "Egon", LastName = "Mueller", Contact = "em@acme.org", UserType = UserTypeEnum.Pro }; + + // ensure we are using the attributes + storageContext.AddAttributeMapper(); + + // ensure the table exists + await storageContext.CreateTableAsync(); + + // inser the model + await storageContext.MergeOrInsertAsync(user); + + // query all + var result = await storageContext.QueryAsync(); + Assert.Single(result); + Assert.Equal("Egon", result.First().FirstName); + Assert.Equal("Mueller", result.First().LastName); + Assert.Equal("em@acme.org", result.First().Contact); + Assert.Equal(UserTypeEnum.Pro, result.First().UserType); + + // Clean up + await storageContext.DeleteAsync(result); + result = await storageContext.QueryAsync(); + Assert.NotNull(result); + Assert.Empty(result); + + await storageContext.DropTableAsync(); + } + } + } +} diff --git a/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs b/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs new file mode 100644 index 0000000..cfbf97f --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/UserModel4.cs @@ -0,0 +1,29 @@ +using System; +using CoreHelpers.WindowsAzure.Storage.Table.Attributes; + +namespace CoreHelpers.WindowsAzure.Storage.Table.Tests.Models +{ + + public enum UserTypeEnum + { + Free, + Pro + } + + [Storable()] + public class UserModel4 + { + [PartitionKey] + public string P { get; set; } = "Partition01"; + + [RowKey] + public string Contact { get; set; } = String.Empty; + + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + + [StoreEnumAsString] + public UserTypeEnum UserType { get; set; } + + } +} \ No newline at end of file diff --git a/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StoreEnumAsStringAttribute.cs b/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StoreEnumAsStringAttribute.cs new file mode 100644 index 0000000..67192b2 --- /dev/null +++ b/CoreHelpers.WindowsAzure.Storage.Table/Attributes/StoreEnumAsStringAttribute.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections; +using System.Reflection; +using CoreHelpers.WindowsAzure.Storage.Table.Serialization; +using Newtonsoft.Json; + +namespace CoreHelpers.WindowsAzure.Storage.Table.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class StoreEnumAsStringAttribute : Attribute, IVirtualTypeAttribute + { + protected Type ObjectType { get; set; } + + public StoreEnumAsStringAttribute() + {} + + public StoreEnumAsStringAttribute(Type objectType) + { + ObjectType = objectType; + } + + public void WriteProperty(PropertyInfo propertyInfo, T obj, TableEntityBuilder builder) + { + // get the value + var element = propertyInfo.GetValue(obj); + if (element == null) + return; + + // convert to strong + var stringifiedElement = (element as Enum)?.ToString("F"); + + // add the property + builder.AddProperty(propertyInfo.Name, stringifiedElement); + } + + public void ReadProperty(Azure.Data.Tables.TableEntity dataObject, PropertyInfo propertyInfo, T obj) + { + // check if we have the property in our entity othetwise move forward + if (!dataObject.ContainsKey(propertyInfo.Name)) + return; + + // get the string value + var stringValue = Convert.ToString(dataObject[propertyInfo.Name]); + + // prepare the value + var resultValue = Enum.Parse(propertyInfo.PropertyType, stringValue); + + + // set the value + propertyInfo.SetValue(obj, resultValue); + } + } +} diff --git a/README.md b/README.md index 99ebc39..2d163a5 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,29 @@ public class VDictionaryModel } ``` +## Store Enum as String Attribute +The store enum as string attribute allows to store enum values as string in Azure Table Store with the following code: + +```csharp +[Storable(Tablename: "EnumModel")] +public class EnumtModel +{ + + public enum TestEnum + { + First, + Second + } + + [PartitionKey] + [RowKey] + public string UUID { get; set; } + + [StoreEnumAsString] + public TestEnum Data { get; set; }; +} +``` + ## Store as JSON Object Attribute The store as JSON attribute allows to store refenrenced objects as json payload for a specific property