2
Azure表存儲does not support許多屬性類型(列表<>,TimeSpan等)。在ASP.NET 5 DNX Core Azure Tables中使用自定義屬性類型
有像Lucifure Stash和Lokad.Cloud這樣的解決方案,但它們不針對DNX Core 5.0進行編譯。
有沒有辦法在使用DNX Core的Azure Tables中添加對自定義屬性類型的支持?
Azure表存儲does not support許多屬性類型(列表<>,TimeSpan等)。在ASP.NET 5 DNX Core Azure Tables中使用自定義屬性類型
有像Lucifure Stash和Lokad.Cloud這樣的解決方案,但它們不針對DNX Core 5.0進行編譯。
有沒有辦法在使用DNX Core的Azure Tables中添加對自定義屬性類型的支持?
一個解決方案是使用反射遍歷實體的所有「自定義」屬性,並將它們序列化爲JSON字符串。
我們可以覆蓋TableEntity的ReadEntity
和WriteEntity
方法來勾去/系列化:
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
類繼承我們的表實體,我們可以自由的使用性能與支持的任何類型由Json.NET提供。
我們已經注意到這個代碼的問題 - 對property.GetType()的調用幾乎所有屬性都返回false,因爲屬性的類型是「Microsoft.WindowsAzure.Storage.Table.EntityProperty」,所以一切落入解析器。 'TryParseJson'然後將看起來像八進制數字的字符串轉換成八進制的十進制表示形式。 –
@ Zhaph-BenDuguid你是對的,感謝修復!我實際上是在生產中使用它,並在很久以前做出了相同的修復,但忘記了更新代碼,這是我的錯。 我還添加了條件來跳過[IgnoreProperty]屬性的屬性的反序列化/序列化。 – Elringus
是的,它會出現我們已經做了類似的:'!Attribute.IsDefined(property,typeof(JsonIgnoreAttribute))' –