XML对象反序列化到界面 [英] XML Object Deserialization to Interface

查看:117
本文介绍了XML对象反序列化到界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类SccmAction和TicketAction这两种实现接口IDelivery。这些类会从中我只是想拉于交付方法邮件和行为处理队列进行传输。



看来可是,我不能反序列化到一个接口因为当我试图这样做一个 System.NotSupportedException 被抛出。从我所收集的XmlSerializer的需要序列化的具体类型。这是否离开我不得不创建一个实现IDelivery一个抽象类,并从它继承SccmAction和ArsAction?我错过了什么呢?



修改进一步明确



我可能有一个设计缺陷,但我的目的就是拉断的消息包含这些对象队列。我的目的是让即将关闭此队列中的所有对象实现的接口确保应用程序处理的对象只是运行在交付方法。每个对象实施交付会有所不同。



代码反序列化

 使用(SqlConnection的连接= 
新的SqlConnection(的ConnectionString))
{
的SqlCommand命令=新的SqlCommand(ReceiveString,连接);
connection.Open();

SqlDataReader的读卡器= Command.ExecuteReader却();

,而(reader.Read())
{
字节[] = SB(字节[])读卡器[MESSAGE_BODY];
SccmAction SA = DeserializeObject< SccmAction>(某人);
IDelivery n = DeserializeObject< IDelivery>(某人);
}

reader.Close();
}

公共静态牛逼DeserializeObject< T>(字节[] BA)
{
XmlSerializer的XS =新的XmlSerializer(typeof运算(T));
的MemoryStream MemoryStream的=新的MemoryStream(BA);
XmlTextWriter的XmlTextWriter的=新的XmlTextWriter(MemoryStream的,Encoding.UTF8);
回报率(T)xs.Deserialize(MemoryStream的);
}

类和接口

  [Serializable接口] 
公共类SccmAction:IDelivery
{
公共字符串计算机名{获得;组; }
公共字符串集合名{获得;组; }
公共字符串操作{搞定;组; }
公众的DateTime EntryDateTime {搞定;组; }

公共SccmAction(){}

公共无效交付()
{
抛出新NotImplementedException();
}
}

[Serializable接口]
公共类ArsAction:IDelivery
{
公共字符串计算机名{获得;组; }
公共字符串客户名称{搞定;组; }

公共ArsAction(){}

公共无效交付()
{
抛出新NotImplementedException();
}
}

公共接口IDelivery
{
无效交付();
}


解决方案

简而言之,你可以' ŧ序列化接口没有任何肮脏。但是,为什么你想反正序列化的界面,它不持有任何状态。它只有一个方法的声明。



您可能希望创建类中的一个Serialize方法。因此,他们可以单独序列化自己,他们知道他们是哪种类型。



此外,你怎么能指望XmlSerializer的反序列化到一个确切的类型不提供呢?它不能简单地接反序列化什么....



您可以但是改变这一行

  IDelivery n = DeserializeObject< IDelivery>(某人); 



这个

  IDelivery n = DeserializeObject< SccmAction>(某人); 

如果你不知道你是反序列化到最初(ArsAction或SccmAction),那么你可以做什么类型的这样的事情。

 公共静态IDelivery DeserializeFromString(字符串XML)
{
//替换该流不管你是期运用
StringReader strReader =新StringReader(XML);
的XmlReader的读者= XmlTextReader的新(FS); //重要的是使用的XmlReader
reader.MoveToContent(); //移动到根

类名的String = reader.Name.Trim(); //读取类名

//使用空间IDelivery位于
的className =IDeliveryNamespace。 +的className;

//获取类型
型classType所= Type.GetType(的className);

XmlSerializer的序列化=新的XmlSerializer(Type.GetType(的className));
//声明被反序列化的类型的对象变量。
IDelivery我;



//使用Deserialize方法来恢复对象的状态。
I =(IDelivery)Convert.ChangeType(serializer.Deserialize(阅读器),classType所);

回报我;
}



当然,这假设您在Serializable类名称不会改变。含义ArsAction类序列并尽可能我可以从你贴什么情况是这样告诉我们。



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


I have two classes SccmAction and TicketAction which both implement interface IDelivery. These classes will be transmitted on a processing queue from which I just want to pull the message and act upon the Deliver method.

It seems however that I cannot deserialize to an interface because when I attempt to do so a System.NotSupportedException is thrown. From what I have gathered the XMLSerializer requires a concrete type for serialization. Does this leave me having to create an abstract class which implements IDelivery and inheriting SccmAction and ArsAction from it? Have I missed something that?

Edit Further Clarification

I may have a design flaw but my purpose is to pull messages off of a queue containing these objects. My intention was to have all objects coming off of this queue implement the interface ensuring that the application processing the objects just operates on the Deliver method. Each objects implementation of Deliver would vary.

Code to Deserialize

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);
}

Classes and Interface

[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();
}

解决方案

Simply put, you can't serialize an interface without any dirtiness. But why do you want to serialize your interface anyway, it doesn't hold any state. It only has a declaration for a method.

You might want to create a Serialize method inside your classes. So they can serialize themselves individually, they know which type they are.

Besides, how do you expect the XmlSerializer to Deserialize to an exact type without providing it? It can't simply pick what to Deserialize to....

You could however change this line

IDelivery iD = DeserializeObject<IDelivery>(sb);

to this

IDelivery iD = DeserializeObject<SccmAction>(sb);

If you dont know what type you are deserializing to initially (ArsAction or SccmAction), then you can do something like this.

 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;
}

Of course this assumes that you your Serializable class Name is not changed. Meaning ArsAction class serializes to and as far as I can tell from what you posted that is the case.

This code is a little dirty, but it should give you a starting point.

这篇关于XML对象反序列化到界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆