【问题标题】:Redis states that classes marked DataContract are not serializable?Redis 声明标记为 DataContract 的类不可序列化?
【发布时间】:2016-11-21 04:47:14
【问题描述】:

我有以下代码:

[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 作为“已接受”序列化程序(?),因为需要一个更好的术语?

我不想回到我所有的课程并标记为 [Seraliazble] - 我希望(因为它对 AppFabric 来说很好)[DataContract] 和 [DataMember] 为我做这件事......

【问题讨论】:

  • 通过使用 datacontract 属性,我希望它已经是可序列化的 - 根据 DataContract 摘要 - “指定类型定义或实现数据合同并且可由序列化程序序列化,例如 System. Runtime.Serialization.DataContractSerializer" - 我正在寻找一种方法,因此我不需要将所有类也标记为 [Serializable] - 例如,我没有为 AppFabric 标记,因此它与上述不同。
  • 是否抛出异常?如果是这样,您能否分享异常的完整 ToString() 输出,包括异常类型、消息和回溯?
  • DataContractSerializerSerializable 无关,它们是完全独立的序列化机制。抛出异常的任何东西显然都希望使用后者。简要查看 StackExchange.Redis 文档,API 采用字符串值,因此我认为您需要添加导致异常的代码。

标签: c# serialization redis stackexchange.redis


【解决方案1】:

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 存储/检索的值的“原语”。

说到检索,您需要使用 reverse 函数将字节数组反序列化回对象实例:

 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.&lt;name&gt;.age)来实现。

【讨论】:

    猜你喜欢
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多