在带有 ASP.NET 5 DNX 核心的 Azure 表中使用自定义 属性 类型
Using custom property types in Azure Tables with ASP.NET 5 DNX Core
Azure Table 存储 does not support 许多 属性 类型(List<>、TimeSpan 等)。
有 Lucifure Stash 和 Lokad.Cloud 等解决方案,但它们没有针对 DNX Core 5.0 进行编译。
是否可以通过 DNX Core 在 Azure Table 中添加对自定义 属性 类型的支持?
一种解决方案是使用反射遍历实体的所有“自定义”属性并将它们序列化为 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<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; }
}
}
现在,如果我们从 CustomEntity
class 继承我们的 table 实体,我们可以自由地使用 Json.NET 支持的任何类型的属性。
Azure Table 存储 does not support 许多 属性 类型(List<>、TimeSpan 等)。
有 Lucifure Stash 和 Lokad.Cloud 等解决方案,但它们没有针对 DNX Core 5.0 进行编译。
是否可以通过 DNX Core 在 Azure Table 中添加对自定义 属性 类型的支持?
一种解决方案是使用反射遍历实体的所有“自定义”属性并将它们序列化为 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<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; }
}
}
现在,如果我们从 CustomEntity
class 继承我们的 table 实体,我们可以自由地使用 Json.NET 支持的任何类型的属性。