这是一般反序列化对象的好方法吗?

时间:2010-05-06 22:55:49

标签: c# generics serialization

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

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

我有一个如下所示的界面:

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<T>看起来像这样:

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<T>(或类似的东西),我现在想要使用处理程序填充一个集合,每个处理程序处理不同的IMessageApple*,{{1我的例子中有}和Banana*个类)。然后我想调用特定消息上的每个处理程序的Coconut*方法,看它是否可以反序列化。如果我得到一个null结果,移动到下一个处理程序;否则,该消息已被反序列化。

看起来像这样:

我做了这样的事情:

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<AppleMessage>,即使IMessageHandler<IMessage>AppleMessage }。有没有不同的方法来做到这一点?

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

1 个答案:

答案 0 :(得分:1)

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

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