我有以下代码:
[DataContract(Namespace = "removed")]
public class FootballPlayer
{
/// <summary>
/// Id of the player.
/// </summary>
[DataMember]
public int Id { get; set; }
/// <summary>
/// Name of the player.
/// </summary>
[DataMember]
public string Name { get; set; }
当我尝试填充我的redis缓存时,我收到以下错误:
Additional information: Type 'FootballApp.PlayerBase.Contract.FootballPlayer' in Assembly 'FootballApp.PlayerBase.Contract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
我是否应该做些什么来告诉Redis接受DataContractSerializer作为接受的&#39;序列化器(?)缺少一个更好的术语?
我不想要回到我所有的课程并标记为[Serialiazble] - 我希望(对于AppFabric来说很好),[DataContract]和[DataMember]为我这样做。 ..
答案 0 :(得分:3)
Redis本身肯定不知道DataContractAttribute,甚至不知道.NET。
StackExchange.Redis,AFAIK也不知道它,也就是它没有内置的支持 - 至少a search in the GitHub repository不会产生一次点击。
以下是我使用StackExchange.Redis在Redis中存储“DataContract对象”所做的工作 - 手动序列化/反序列化:
private static byte[] GetBuffer<T>(T obj) {
using (var m = new MemoryStream()) {
var ser = new DataContractSerializer(obj.GetType());
ser.WriteObject(m, obj);
return m.ToArray();
}
}
然后,您可以从该字节数组构建一个RedisValue
实例,它是StackExchange.Redis用于处理从Redis存储/检索的值的“原语”。
说到检索,你需要使用反向函数将字节数组反序列化回对象实例:
private static T GetObject<T>(byte[] buffer) {
using (var m = new MemoryStream(buffer)) {
var ser = new DataContractSerializer(typeof(T));
return (T)ser.ReadObject(m);
}
}
当然,你可能想隐藏一些抽象或扩展方法背后的东西。
最后,您可能希望重新考虑您的设计。根据您的应用程序,不将完整对象(图形)存储为redis中的blob,而将单个属性作为单个键(和关联值)存储可能很有价值。因此,如果您只需要一个(或几个)属性,那么您将无需序列化/传输/反序列化整块字节的成本 - 当然您可能有更多的网络往返。正如我所说,这取决于你的申请。
此外,您可以使用Redis的API(甚至是LUA脚本)有效地操作和处理您的数据,而无需首先进行传输。您可以使用Redis'data types或命名方案(例如users.<name>.age
)来实现此目的。