Redis声明标记为DataContract的类不可序列化?

时间:2016-07-18 14:18:18

标签: c# serialization redis stackexchange.redis

我有以下代码:

[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]为我这样做。 ..

1 个答案:

答案 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)来实现此目的。