【问题标题】:Is this a good way to generically deserialize objects?这是一般反序列化对象的好方法吗?
【发布时间】:2010-05-06 22:55:49
【问题描述】:

我有一个流,表示消息的序列化对象会定期转储到该流上。对象是数量非常有限的类型之一,除了实际到达的字节序列外,我无法知道它是什么类型的消息。

我想简单地尝试将其反序列化为特定类型的对象,如果抛出异常,请使用下一个类型重试。

我的界面如下所示:

public interface IMessageHandler<T> where T : class, IMessage { 
  T Handle(string message);
}

// elsewhere:

// (These are all xsd.exe-generated classes from an XML schema.)
public class AppleMessage : IMessage { ... }
public class BananaMessage : IMessage { ... }
public class CoconutMessage : IMessage { ... }

然后我写了一个GenericHandler&lt;T&gt;,看起来像这样:

public class GenericHandler<T> : IMessageHandler<T> where T: class, IMessage {
  public class MessageHandler : IMessageHandler {
    T IMessageHandler.Handle(string message) {
      T result = default(T);

      try {
        // This utility method tries to deserialize the object with an 
        // XmlSerializer as if it were an object of type T.
        result = Utils.SerializationHelper.Deserialize<T>(message);
      } catch (InvalidCastException e) {
        result = default(T);
      }

      return result;
    }
  }
}

使用我的GenericHandler&lt;T&gt;(或类似的东西),我现在想用处理程序填充一个集合,每个处理程序处理不同的IMessageApple*Banana*Coconut* 类在我的例子中)。然后我想在特定消息上调用每个处理程序的Handle 方法,看看它是否可以反序列化。如果我得到一个空结果,则转到下一个处理程序;否则,消息已被反序列化。

看起来像这样:

我最终做了这样的事情:

public object Process(string message) {
  var handlers = new ArrayList {
    new MessageHandler<AppleMessage>(),
    new MessageHandler<BananaMessage>(),
    new MessageHandler<CoconutMessage>(),
  }

  foreach (IMessageHandler<IMessage> h in handlers) {
    var result = h.Handle(message);

    // Message successfully handled! Return the result.
    if (result != null) { return result; }
  }

  // Couldn't handle the message; return null.
  return null;
}

我很确定由于协方差限制,这不会起作用,但是,因为 IMessageHandler&lt;AppleMessage&gt; 不是 IMessageHandler&lt;IMessage&gt;,即使 AppleMessageIMessage。有没有其他方法可以做到这一点?

此外,有没有更好的方法来反序列化未知(但受限)类型的数据?

【问题讨论】:

    标签: c# generics serialization


    【解决方案1】:

    使用指示类型的字段扩展您的消息,以便您可以选择正确的反序列化器。

    (可选)使用现有协议,例如 protobuf,这样您就不必重新发明轮子。

    【讨论】:

    • +1 表示不重新发明。这个问题之前肯定已经解决了。
    猜你喜欢
    • 2015-06-01
    • 2011-05-30
    • 1970-01-01
    • 2017-02-05
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    相关资源
    最近更新 更多