问题
Azure Table Storage does not support many property types (List<>, TimeSpan, etc).
There are solutions like Lucifure Stash and Lokad.Cloud, but they are not compiling for DNX Core 5.0.
Is there a way to add support for custom property types in Azure Tables with DNX Core?
回答1:
One solution is to use reflection to iterate through all the “custom” properties of the entity and serialize them to JSON strings.
We can override TableEntity’s ReadEntity
and WriteEntity
methods to hook de-/serialization:
using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public abstract class CustomEntity : TableEntity
{
public override IDictionary<string, EntityProperty> WriteEntity (OperationContext operationContext)
{
var properties = base.WriteEntity(operationContext);
// Iterating through the properties of the entity
foreach (var property in GetType().GetProperties().Where(property =>
// Excluding props explicitly marked to ignore serialization
!property.GetCustomAttributes<IgnorePropertyAttribute>(true).Any() &&
// Excluding already serialized props
!properties.ContainsKey(property.Name) &&
// Excluding internal TableEntity props
typeof(TableEntity).GetProperties().All(p => p.Name != property.Name)))
{
var value = property.GetValue(this);
if (value != null)
// Serializing property to JSON
properties.Add(property.Name, new EntityProperty(JsonConvert.SerializeObject(value)));
}
return properties;
}
public override void ReadEntity (IDictionary<string, EntityProperty> properties, OperationContext operationContext)
{
base.ReadEntity(properties, operationContext);
// Iterating through the properties of the entity
foreach (var property in GetType().GetProperties().Where(property =>
// Excluding props explicitly marked to ignore serialization
!property.GetCustomAttributes<IgnorePropertyAttribute>(true).Any() &&
// Excluding props which were not originally serialized
properties.ContainsKey(property.Name) &&
// Excluding props with target type of string (they are natively supported)
property.PropertyType != typeof(string) &&
// Excluding non-string table fields (this will filter-out
// all the remaining natively supported props like byte, DateTime, etc)
properties[property.Name].PropertyType == EdmType.String))
{
// Checking if property contains a valid JSON
var jToken = TryParseJson(properties[property.Name].StringValue);
if (jToken != null)
{
// Constructing method for deserialization
var toObjectMethod = jToken.GetType().GetMethod("ToObject", new[] { typeof(Type) });
// Invoking the method with the target property type; eg, jToken.ToObject(CustomType)
var value = toObjectMethod.Invoke(jToken, new object[] { property.PropertyType });
property.SetValue(this, value);
}
}
}
private static JToken TryParseJson (string s)
{
try { return JToken.Parse(s); }
catch (JsonReaderException) { return null; }
}
}
Now, if we inherit our table entities from the CustomEntity
class, we can freely use properties with any types supported by Json.NET.
来源:https://stackoverflow.com/questions/34557105/using-custom-property-types-in-azure-tables-with-asp-net-5-dnx-core