Skip to content

Instantly share code, notes, and snippets.

@gongdo
Created December 17, 2015 09:33
Show Gist options
  • Save gongdo/3f67715faaac346631ce to your computer and use it in GitHub Desktop.
Save gongdo/3f67715faaac346631ce to your computer and use it in GitHub Desktop.
StringEnumTableEntity that extends TableEntity in order to support enum properties when Read/WriteEntity.
/// <summary>
/// Represents the base object type for a table entity in the Table service.
/// </summary>
/// <remarks>
/// ReadEntity deserializes enum properties from string values which have same name.
/// Property name comparison is case-insensitive.
/// Also WriteEntity serializes enum properties as string values.
/// </remarks>
public abstract class StringEnumTableEntity : TableEntity
{
private readonly IReadOnlyDictionary<string, PropertyInfo>
EnumProperties;
public StringEnumTableEntity()
{
EnumProperties = GetEnumProperties(GetType());
}
public StringEnumTableEntity(string partitionKey, string rowKey)
: base(partitionKey, rowKey)
{
EnumProperties = GetEnumProperties(GetType());
}
private static Dictionary<string, PropertyInfo>
GetEnumProperties(Type type)
{
return type.GetTypeInfo()
.DeclaredProperties
.Where(p => p.PropertyType.GetTypeInfo().IsEnum)
.ToDictionary(p => p.Name, p => p);
}
public override void ReadEntity(
IDictionary<string, EntityProperty> properties,
OperationContext operationContext)
{
base.ReadEntity(properties, operationContext);
properties
.Where(p => EnumProperties.ContainsKey(p.Key))
.Select(p => new
{
p.Value.StringValue,
Property = EnumProperties[p.Key]
})
.ToList()
.ForEach(item =>
{
var enumValue = Enum.Parse(
item.Property.PropertyType,
item.StringValue);
item.Property.SetValue(this, enumValue);
});
}
public override IDictionary<string, EntityProperty> WriteEntity(
OperationContext operationContext)
{
var dictionary = base.WriteEntity(operationContext);
EnumProperties
.Select(p => new
{
p.Key,
Value = p.Value.GetValue(this).ToString(),
})
.ToList()
.ForEach(item =>
{
dictionary.Add(item.Key, new EntityProperty(item.Value));
});
return dictionary;
}
}
public class StringEnumTableEntityTest
{
[Fact]
public void WriteEntity_adds_enum_properties()
{
var entity = new DummyEntity();
var values = entity.WriteEntity(null);
Assert.Equal(DummyEnum.Cat.ToString(), values["Enum1"].StringValue);
Assert.Equal(DummyEnum.Dog.ToString(), values["Enum2"].StringValue);
}
[Fact]
public void ReadEntity_sets_enum_properties()
{
var entity = new DummyEntity();
entity.ReadEntity(new Dictionary<string, EntityProperty>
{
{ "Enum1", EntityProperty.GeneratePropertyForString(DummyEnum.Dog.ToString()) },
{ "Enum2", EntityProperty.GeneratePropertyForString(DummyEnum.Cat.ToString()) },
}, null);
Assert.Equal(DummyEnum.Dog, entity.Enum1);
Assert.Equal(DummyEnum.Cat, entity.Enum2);
}
[Fact]
public void ReadEntity_ignores_case()
{
var entity = new DummyEntity();
entity.ReadEntity(new Dictionary<string, EntityProperty>
{
{ "eNum1", EntityProperty.GeneratePropertyForString(DummyEnum.Dog.ToString()) },
{ "enUm2", EntityProperty.GeneratePropertyForString(DummyEnum.Cat.ToString()) },
}, null);
Assert.Equal(DummyEnum.Dog, entity.Enum1);
Assert.Equal(DummyEnum.Cat, entity.Enum2);
}
public enum DummyEnum
{
Cat,
Dog,
Monkey
}
public class DummyEntity : StringEnumTableEntity
{
public DummyEnum Enum1 { get; set; } = DummyEnum.Cat;
public DummyEnum Enum2 { get; set; } = DummyEnum.Dog;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment