Azure表存储不支持许多属性类型(List <>,TimeSpan等).
有一些解决方案,如Lucifure Stash和Lokad.Cloud,但他们没有为DNX Core 5.0编译.
有没有办法在使用DNX Core的Azure表中添加对自定义属性类型的支持?
一种解决方案是使用反射来遍历实体的所有"自定义"属性,并将它们序列化为JSON字符串.
我们可以覆盖TableEntity ReadEntity
和WriteEntity
方法来挂钩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 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(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 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(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; }
}
}
现在,如果我们从CustomEntity
类继承我们的表实体,我们可以自由地使用Json.NET支持的任何类型的属性.