XML对象反序列化到接口

时间:2009-07-17 21:31:32

标签: c# serialization interface xml-serialization

我有两个SccmAction和TicketAction类,它们都实现了接口IDelivery。这些类将在一个处理队列上传输,我只想从中获取消息并对Deliver方法采取行动。

但是我似乎无法反序列化到接口,因为当我尝试这样做时,会抛出 System.NotSupportedException 。根据我收集的内容,XMLSerializer需要一个具体的类型来进行序列化。这是否让我不得不创建一个实现IDelivery并从中继承SccmAction和ArsAction的抽象类?我错过了什么吗?

编辑进一步澄清

我可能有设计缺陷,但我的目的是从包含这些对象的队列中提取消息。我的目的是让所有离开此队列的对象实现接口,确保处理对象的应用程序只对Deliver方法进行操作。 Deliver的每个对象实现都会有所不同。

反序列化代码

using (SqlConnection connection =
    new SqlConnection(ConnectionString))
{
    SqlCommand command = new SqlCommand(ReceiveString, connection);
    connection.Open();

    SqlDataReader reader = command.ExecuteReader();

    while (reader.Read())
    {
        byte[] sb = (byte[])reader["message_body"];
        SccmAction sa = DeserializeObject<SccmAction>(sb);
        IDelivery iD = DeserializeObject<IDelivery>(sb);
    }

    reader.Close();
}

public static T DeserializeObject<T>(byte[] ba)
{
    XmlSerializer xs = new XmlSerializer(typeof(T));
    MemoryStream memoryStream = new MemoryStream(ba);
    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
    return (T)xs.Deserialize(memoryStream);
}

类和接口

[Serializable]
public class SccmAction : IDelivery
{
    public string MachineName { get; set; }
    public string CollectionName { get; set; }
    public string Action { get; set; }
    public DateTime EntryDateTime { get; set; }

    public SccmAction () { }

    public void Deliver()
    {
        throw new NotImplementedException();
    }
}

[Serializable]
public class ArsAction : IDelivery
{
    public string MachineName { get; set; }
    public string CustomerName { get; set; }

    public ArsAction() { }

    public void Deliver()
    {
        throw new NotImplementedException();
    }
}

public interface IDelivery
{
    void Deliver();
}

1 个答案:

答案 0 :(得分:4)

简单地说,您无法在没有任何肮脏的情况下序列化界面。但是,为什么你想要序列化你的界面,它没有任何状态。它只有一个方法声明。

您可能希望在类中创建Serialize方法。所以他们可以单独序列化,他们知道他们是哪种类型。

此外,您如何期望XmlSerializer在不提供的情况下反序列化为精确类型?它不能简单地选择反序列化的内容......

然而,您可以更改此行

IDelivery iD = DeserializeObject<IDelivery>(sb);

到这个

IDelivery iD = DeserializeObject<SccmAction>(sb);

如果您不知道最初要反序列化的类型(ArsAction或SccmAction),那么您可以执行类似的操作。

public static IDelivery DeserializeFromString(string xml)
{
      //replace this stream with whatever you are useing
      StringReader strReader = new StringReader(xml);
      XmlReader reader = new XmlTextReader(fs); //important to use XmlReader
      reader.MoveToContent(); //move to root

      String className = reader.Name.Trim(); //read the class name 

      //use the namespace IDelivery is located in
      className  = "IDeliveryNamespace." + className;

      //get the type
      Type classType = Type.GetType(className);

      XmlSerializer serializer = new XmlSerializer(Type.GetType(className));      

      // Declare an object variable of the type to be deserialized.
      IDelivery i;
      // Use the Deserialize method to restore the object's state.
      i = (IDelivery)Convert.ChangeType(serializer.Deserialize(reader),classType);
      return i;
}

当然,这假设您的Serializable类名称未更改。意思是ArsAction类序列化,并且据我所知,你可以告诉我的情况。

这段代码有点脏,但它应该给你一个起点。