如何将包含对象(任何可序列化类型)的类序列化为XML? (条件:.NET 1.1)

时间:2011-09-21 13:53:22

标签: c# xml vb.net serialization xml-serialization

问题:我必须在.NET 1.1下的HttpModule中获取所有会话的内容... (不要问我为什么某些人仍然使用它)

我可以写模块,我可以得到会话。 但是......会话存储为

session["SomeString"] = object

如何将包含对象的类序列化为XML的成员? 具体来说,我尝试了一个DataTable的例子。

条件:它必须适用于.NET 1.1所以没有泛型

由于1.1没有System.Web.SessionState,所以不是这样:

  private string Serialize(System.Web.SessionState.SessionStateItemCollection items)
    {
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms);

        if (items != null)
            items.Serialize(writer);

        writer.Close();

        return Convert.ToBase64String(ms.ToArray());
    } // End Function Serialize

下面是我的尝试,它在对象中仅对文本值有效,但在DataTable上失败。有趣的是:DataTable是可序列化的,所以它“应该”工作......

using System;
using System.Collections.Generic;
using System.Text;

    namespace SessionModuleUnitTest
    {


        public class Program
        {

            [Serializable()]
            public class kvp
            {
                [System.Xml.Serialization.XmlElement(ElementName = "key")]
                public string key = "";

                [System.Xml.Serialization.XmlElement(ElementName = "value")]
                public object value = new object();

                public kvp()
                { }

                public kvp(string strKey, object obj)
                {

                    this.key = strKey;


                    this.value = obj;
                }

            }

            [Serializable()]
            public class whatever
            {
                [System.Xml.Serialization.XmlArrayItem(Type = typeof(kvp))]
                public kvp[] MyKeyValueCollection;
            }


            public static void Serialization()
            {
                // http://www.java2s.com/Tutorial/CSharp/0220__Data-Structure/SerializeanArrayListobjecttoabinaryfile.htm
                // http://www.java2s.com/Tutorial/CSharp/0220__Data-Structure/DeserializeanArrayListobjectfromabinaryfile.htm

                System.Data.DataTable dt = new System.Data.DataTable();
                dt.Columns.Add("abc", typeof(string));
                dt.Columns.Add("def", typeof(int));

                System.Data.DataRow dr = dt.NewRow();
                dr["abc"] = "test1";
                dr["def"] = 123;
                dt.Rows.Add(dr);


                dr = dt.NewRow();
                dr["abc"] = "test2";
                dr["def"] = 456;
                dt.Rows.Add(dr);

                System.Data.DataSet ds = new System.Data.DataSet();
                ds.Tables.Add(dt);

                Console.WriteLine("Type: " + dt.GetType().FullName + ", Serializable: " + dt.GetType().IsSerializable);

                kvp ObjectToSerialize1 = new kvp("key1", "value1");
                kvp ObjectToSerialize2 = new kvp("key2", "value2");
                kvp ObjectToSerialize3 = new kvp("key3", dt);




                System.Collections.ArrayList al = new System.Collections.ArrayList();
                al.Add(ObjectToSerialize1);
                al.Add(ObjectToSerialize2);
                al.Add(ObjectToSerialize3);

                whatever what = new whatever();
                what.MyKeyValueCollection = new kvp[3];
                what.MyKeyValueCollection[0] = ObjectToSerialize1;
                what.MyKeyValueCollection[1] = ObjectToSerialize2;
                what.MyKeyValueCollection[2] = ObjectToSerialize3;


                Type[] theExtraTypes = new Type[2];
                //theExtraTypes[0] = typeof(System.Collections.ArrayList);
                theExtraTypes[0] = typeof(kvp);
                //theExtraTypes[2] = typeof(System.Data.DataTable);


                System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(what.GetType());
                //System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(what.GetType(), theExtraTypes);
                //System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(al.GetType());
                //System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(System.Collections.ArrayList), theExtraTypes);
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                System.IO.StringWriter writer = new System.IO.StringWriter(sb);
                //ser.Serialize(writer, al);    // Here Classes are converted to XML String. 
                ser.Serialize(writer, what);    // Here Classes are converted to XML String. 
                // This can be viewed in SB or writer.
                // Above XML in SB can be loaded in XmlDocument object

                string strSerializedItem = sb.ToString();
                Console.WriteLine(strSerializedItem);

                /*
                System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
                xmlDoc.LoadXml(sb.ToString());


                System.IO.StringWriter sw = new System.IO.StringWriter();
                System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw);
                xmlDoc.WriteTo(xw);
                string strSerialized = sw.ToString();
                xw.Close();
                sw.Close();
                //sw.Dispose();
                */
            }



            static void Main(string[] args)
            {
                Serialization();
                Console.WriteLine(Environment.NewLine);
                Console.WriteLine(" --- Press any key to continue --- ");
                Console.ReadKey(true);
            }


        }


    }

修改
显然,运行时序列化和XML序列化之间存在差异 在这里阅读:
http://www.codeproject.com/KB/aspnet/Serialization.aspx
在这里 http://manishagrahari.blogspot.com/2011/08/serialization-in-net-part-4.html
在这里 http://blog.kowalczyk.info/article/Serialization-in-C.html
在这里 http://www.codeproject.com/KB/XML/Serialization_Samples.aspx

这里有核心方法:
http://www.15seconds.com/issue/020903.htm
而这个 http://www.codeproject.com/KB/XML/Serialization_Samples.aspx

对于SOAP序列化,您需要添加对以下内容的引用:
System.Runtime.Serialization.Formatters.Soap

2 个答案:

答案 0 :(得分:1)

一般情况下,你不能这样做。可以将事物置于无法进行XML序列化的会话状态。

答案 1 :(得分:-1)

这很可能 这是一场艰苦的战斗,但这是有可能的。

简言之77:
使用属性,将对象序列化为字符串,然后将两个字符串(以及类型信息,INCLUDING assemblyname)保存在arraylist中的容器类型中,然后序列化此ArrayList。

然后是反序列化的反向技巧。 第三方请注意,我可能没有正确捕获对象可能无法序列化的情况。例如,使用非可序列化类型(如字典)来测试它。

using System;
using System.Collections.Generic;
using System.Text;


namespace SessionModuleUnitTest
{


    public class Program
    {


        [Serializable()]
        [System.Xml.Serialization.XmlRoot(ElementName = "SessionData")]
        public class cSessionData
        {

            [System.Xml.Serialization.XmlElement(ElementName = "key")]
            public string key;

            [System.Xml.Serialization.XmlElement(ElementName = "assembly")]
            public string AssemblyQualifiedName;

            [System.Xml.Serialization.XmlElement(ElementName = "value")]
            public string m_value;

            [System.Xml.Serialization.XmlIgnore()]
            public object value
            {

                get 
                {
                    object obj = null;

                    if (m_value == null)
                        return obj;

                    // Type.GetType only looks in the currently executing assembly and mscorlib 
                    // unless you specify the assembly name as well.
                    //Type T = Type.GetType(this.datatype);
                    Type T = Type.GetType(this.AssemblyQualifiedName);

                    System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(T);

                    System.IO.StringReader sr = new System.IO.StringReader(m_value);
                    obj = ser.Deserialize(sr);
                    sr.Close();
                    //sr.Dispose();
                    sr = null;
                    ser = null;

                    return obj; 
                } // End Get

                set
                { 
                    //this.m_value = value;
                    //Console.WriteLine("Type: " + obj.GetType().FullName + ", Serializable: " + obj.GetType().IsSerializable);

                    if (value != null)
                    {
                        //this.datatype = value.GetType().FullName;
                        this.AssemblyQualifiedName = value.GetType().AssemblyQualifiedName;

                        if (value.GetType().IsSerializable)
                        {
                            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(value.GetType());
                            System.Text.StringBuilder sb = new System.Text.StringBuilder();
                            System.IO.StringWriter writer = new System.IO.StringWriter(sb);
                            ser.Serialize(writer, value);
                            this.m_value = sb.ToString();
                            writer.Close();
                            //writer.Dispose();
                            sb = null;
                            writer = null;
                            ser = null;
                        }
                        else
                            this.m_value = null;
                    }
                    else
                    {
                        this.AssemblyQualifiedName = null;
                        this.m_value = null;
                    }
                } // End Set
            } // End Property value


            public cSessionData()
            { 
            } // End Constructor


            public cSessionData(string strKey, object obj)
            {
                this.key = strKey;
                this.value = obj;
            } // End Constructor


        } // End Class cSessionData


        public static string Serialize(System.Collections.ArrayList al)
        {
            Type[] theExtraTypes = new Type[2];
            theExtraTypes[0] = typeof(System.Collections.ArrayList);
            theExtraTypes[1] = typeof(cSessionData);

            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(System.Collections.ArrayList), theExtraTypes);
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            System.IO.StringWriter writer = new System.IO.StringWriter(sb);

            ser.Serialize(writer, al);
            string strSerializedItem = sb.ToString();
            sb = null;
            writer.Close();
            //writer.Dispose();
            writer = null;
            ser = null;

            /*
            System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
            xmlDoc.LoadXml(sb.ToString());


            System.IO.StringWriter sw = new System.IO.StringWriter();
            System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw);
            xmlDoc.WriteTo(xw);
            string strSerialized = sw.ToString();
            xw.Close();
            sw.Close();
            //sw.Dispose();
            */
            return strSerializedItem;
        }


        public static void Serialization()
        {
            // http://www.java2s.com/Tutorial/CSharp/0220__Data-Structure/SerializeanArrayListobjecttoabinaryfile.htm
            // http://www.java2s.com/Tutorial/CSharp/0220__Data-Structure/DeserializeanArrayListobjectfromabinaryfile.htm

            System.Data.DataTable dt = new System.Data.DataTable();
            dt.Columns.Add("abc", typeof(string));
            dt.Columns.Add("def", typeof(int));

            System.Data.DataRow dr = dt.NewRow();
            dr["abc"] = "test1";
            dr["def"] = 123;
            dt.Rows.Add(dr);


            dr = dt.NewRow();
            dr["abc"] = "test2";
            dr["def"] = 456;
            dt.Rows.Add(dr);

            System.Data.DataSet ds = new System.Data.DataSet();
            ds.Tables.Add(dt);

            Console.WriteLine("tname: " + dt.GetType().FullName);

            cSessionData ObjectToSerialize1 = new cSessionData("key1", "value1");
            cSessionData ObjectToSerialize2 = new cSessionData("key2", "value2");
            cSessionData ObjectToSerialize3 = new cSessionData("key3", dt);


            System.Collections.ArrayList al = new System.Collections.ArrayList();
            al.Add(ObjectToSerialize1);
            al.Add(ObjectToSerialize2);
            al.Add(ObjectToSerialize3);

            string strSerializedItem = Serialize(al);
            Console.WriteLine(strSerializedItem);
            Deserialize(strSerializedItem);
        }


        static void Deserialize(string strXML)
        {
            Type[] theExtraTypes = new Type[2];
            theExtraTypes[0] = typeof(System.Collections.ArrayList);
            theExtraTypes[1] = typeof(cSessionData);


            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(System.Collections.ArrayList), theExtraTypes);

            System.IO.StringReader sr = new System.IO.StringReader(strXML);
            System.Collections.ArrayList myal = (System.Collections.ArrayList ) ser.Deserialize(sr);
            foreach (cSessionData SessionData in myal)
            {
                Console.WriteLine(SessionData.key + "=" + SessionData.value);
            }

            cSessionData MySessionData = (cSessionData) myal[2];
            Console.WriteLine(MySessionData.key + "=" + MySessionData.value);
            System.Data.DataTable d = (System.Data.DataTable)MySessionData.value;
            Console.WriteLine(d.Rows[0]["def"]);
        } // End Sub Deserialize


        static void Main(string[] args)
        {
            Serialization();
            Console.WriteLine(Environment.NewLine);
            Console.WriteLine(" --- Press any key to continue --- ");
            Console.ReadKey(true);
        } // End Sub Main


    } // End Class Program


} // Namespace SessionModuleUnitTest

编辑: 第1版:

using System;
using System.Collections.Generic;
using System.Text;


namespace SessionModuleUnitTest
{


    public class Program
    {


        [Serializable()]
        [System.Xml.Serialization.XmlRoot(ElementName = "SessionData")]
        public class cSessionData
        {

            [System.Xml.Serialization.XmlElement(ElementName = "key")]
            public string key;

            [System.Xml.Serialization.XmlElement(ElementName = "assembly")]
            public string AssemblyQualifiedName;

            [System.Xml.Serialization.XmlElement(ElementName = "value")]
            public string m_value;

            [System.Xml.Serialization.XmlIgnore()]
            public object value
            {

                get 
                {
                    object obj = null;

                    if (m_value == null)
                        return obj;

                    // Type.GetType only looks in the currently executing assembly and mscorlib 
                    // unless you specify the assembly name as well.
                    //Type T = Type.GetType(this.datatype);
                    Type T = Type.GetType(this.AssemblyQualifiedName);
                    obj = DeSerializeSOAP(m_value);

                    return obj; 
                } // End Get

                set
                { 
                    //this.m_value = value;
                    //Console.WriteLine("Type: " + obj.GetType().FullName + ", Serializable: " + obj.GetType().IsSerializable);

                    if (value != null)
                    {
                        //this.datatype = value.GetType().FullName;
                        this.AssemblyQualifiedName = value.GetType().AssemblyQualifiedName;

                        if (value.GetType().IsSerializable)
                        {
                            this.m_value = SerializeSOAP(value);
                        }
                        else
                            this.m_value = null;
                    }
                    else
                    {
                        this.AssemblyQualifiedName = null;
                        this.m_value = null;
                    }
                } // End Set
            } // End Property value


            public cSessionData()
            { 
            } // End Constructor


            public cSessionData(string strKey, object obj)
            {
                this.key = strKey;
                this.value = obj;
            } // End Constructor


        } // End Class cSessionData


        //public static void InsertSessionData(cSessionData SessionData)
        public static void InsertSessionData(string strSessionUID, string strSessionID, string strKey, string strValue, string strDataType)
        {
            strSessionUID = strSessionUID.Replace("'", "''");
            strSessionID = strSessionID.Replace("'", "''");
            strKey = strKey.Replace("'", "''");
            strValue = strValue.Replace("'", "''");
            strDataType = strDataType.Replace("'", "''");

            string strSQL = @"
            INSERT INTO dbo.T_SessionValues
            (
                 Session_UID
                ,Session_ID
                ,Session_Key
                ,Session_Value
                ,Session_DataType
            )
            VALUES
            (
                 '" + strSessionUID + @"'  --<Session_UID, uniqueidentifier, newid()>
                ,N'" + strSessionID + @"'  --<Session_ID, nvarchar(84), NULL>
                ,N'" + strKey + @"'        --<Session_Key, nvarchar(100), NULL>
                ,N'" + strValue + @"'      --<Session_Value, nvarchar(max),NULL>
                ,N'" + strDataType + @"'   --<Session_DataType, nvarchar(4000),NULL>
            )
            ";
            //System.Runtime.Serialization.Formatters.Binary.
            COR.SQL.MS_SQL.Execute(strSQL);
        }



        // Add reference to System.Runtime.Serialization.Formatters.Soap
        public static string SerializeSOAP(object obj)
        {
            string strSOAP = null;
            System.Runtime.Serialization.Formatters.Soap.SoapFormatter serializer = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();

            using (System.IO.MemoryStream memStream = new System.IO.MemoryStream())
            {
                serializer.Serialize(memStream, obj);

                long pos = memStream.Position;
                memStream.Position = 0;

                using (System.IO.StreamReader reader = new System.IO.StreamReader(memStream))
                {
                    strSOAP = reader.ReadToEnd();
                    memStream.Position = pos;
                    reader.Close();
                }
            }
            return strSOAP;
        }


        public static object DeSerializeSOAP(string SOAP)
        {
            if (string.IsNullOrEmpty(SOAP))
            {
                throw new ArgumentException("SOAP can not be null/empty");
            }
            using (System.IO.MemoryStream Stream = new System.IO.MemoryStream(UTF8Encoding.UTF8.GetBytes(SOAP)))
            {
                System.Runtime.Serialization.Formatters.Soap.SoapFormatter Formatter = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
                return Formatter.Deserialize(Stream);
            }
        }


        public static System.Collections.ArrayList GetData()
        {
            System.Data.DataTable dt = new System.Data.DataTable();
            dt.Columns.Add("abc", typeof(string));
            dt.Columns.Add("def", typeof(int));

            System.Data.DataRow dr = dt.NewRow();
            dr["abc"] = "test1";
            dr["def"] = 123;
            dt.Rows.Add(dr);


            dr = dt.NewRow();
            dr["abc"] = "test2";
            dr["def"] = 456;
            dt.Rows.Add(dr);

            System.Data.DataSet ds = new System.Data.DataSet();
            ds.Tables.Add(dt);

            cSessionData ObjectToSerialize1 = new cSessionData("key1", "value1");
            cSessionData ObjectToSerialize2 = new cSessionData("key2", "value2");
            cSessionData ObjectToSerialize3 = new cSessionData("key3", dt);

            System.Collections.ArrayList al = new System.Collections.ArrayList();
            al.Add(ObjectToSerialize1);
            al.Add(ObjectToSerialize2);
            al.Add(ObjectToSerialize3);
            return al;
        }


        public static void Deserialize(string strSOAP)
        {

            System.Collections.ArrayList myal = (System.Collections.ArrayList)DeSerializeSOAP(strSOAP);

            foreach (cSessionData SessionData in myal)
            {
                Console.WriteLine(SessionData.key + "=" + SessionData.value);
            }

            cSessionData MySessionData = (cSessionData)myal[2];
            Console.WriteLine(MySessionData.key + "=" + MySessionData.value);
            System.Data.DataTable d = (System.Data.DataTable)MySessionData.value;
            Console.WriteLine(d.Rows[0]["def"]);
        }


        public static string Serialize(System.Collections.ArrayList al)
        {
            // http://www.java2s.com/Tutorial/CSharp/0220__Data-Structure/SerializeanArrayListobjecttoabinaryfile.htm
            // http://www.java2s.com/Tutorial/CSharp/0220__Data-Structure/DeserializeanArrayListobjectfromabinaryfile.htm

            string strSerializedItem = SerializeSOAP(al);
            Console.WriteLine(strSerializedItem);
            return strSerializedItem;
        }


        static void Main(string[] args)
        {
            //InsertSessionData(System.Guid.NewGuid().ToString(), "fdslfkjsdalfj", "Key1", "Value1", typeof(System.Data.DataTable).AssemblyQualifiedName);
            string strSOAP = Serialize(GetData());
            Deserialize(strSOAP);
            Console.WriteLine(Environment.NewLine);
            Console.WriteLine(" --- Press any key to continue --- ");
            Console.ReadKey(true);
        } // End Sub Main


    } // End Class Program


} // Namespace SessionModuleUnitTest