divyang4481 / xstream-dot-net

Automatically exported from code.google.com/p/xstream-dot-net
1 stars 1 forks source link

Cannot deserialize Hashtable #18

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
When you attempt to deserialize a Hashtable as part of another object, an 
exception is thrown:

Xstream.Core.ConversionException: Couldn't set field node in object : 
Couldn't set field values in object : Couldn't set field buckets in object 
: Object reference not set to an instance of an object. ---> 
System.ApplicationException: Couldn't set field node in object : Couldn't 
set field values in object : Couldn't set field buckets in object : Object 
reference not set to an instance of an object. ---> 
System.ApplicationException: Couldn't set field values in object : Couldn't 
set field buckets in object : Object reference not set to an instance of an 
object. ---> System.ApplicationException: Couldn't set field buckets in 
object : Object reference not set to an instance of an object. ---> 
System.NullReferenceException: Object reference not set to an instance of 
an object.
   at Xstream.Core.MarshalContext.GetTypeFromTag(XmlNode node, Boolean 
isField)
   at Xstream.Core.MarshalContext.GetConverter(XmlNode node, Type& 
type)
   at Xstream.Core.Converters.ArrayConverter.FromXml(Object parent, 
FieldInfo field, Type type, XmlNode xml, IMarshalContext context)
   at Xstream.Core.Converters.ObjectConverter.FromXmlAs(IMarshalContext 
context, Type type, Object value, XmlNode xml)
   --- End of inner exception stack trace ---
   at Xstream.Core.Converters.ObjectConverter.FromXmlAs(IMarshalContext 
context, Type type, Object value, XmlNode xml)
   at Xstream.Core.Converters.ObjectConverter.FromXml(Object parent, 
FieldInfo field, Type type, XmlNode xml, IMarshalContext context)
   at Xstream.Core.Converters.ObjectConverter.FromXmlAs(IMarshalContext 
context, Type type, Object value, XmlNode xml)
   --- End of inner exception stack trace ---
   at Xstream.Core.Converters.ObjectConverter.FromXmlAs(IMarshalContext 
context, Type type, Object value, XmlNode xml)
   at Xstream.Core.Converters.ObjectConverter.FromXml(Object parent, 
FieldInfo field, Type type, XmlNode xml, IMarshalContext context)
   at Xstream.Core.Converters.ObjectConverter.FromXmlAs(IMarshalContext 
context, Type type, Object value, XmlNode xml)
   --- End of inner exception stack trace ---
   at Xstream.Core.Converters.ObjectConverter.FromXmlAs(IMarshalContext 
context, Type type, Object value, XmlNode xml)
   at Xstream.Core.Converters.ObjectConverter.FromXml(Object parent, 
FieldInfo field, Type type, XmlNode xml, IMarshalContext context)
   at Xstream.Core.XStreamMarshaller.FromXml(String xml, IMarshalContext 
context)
   --- End of inner exception stack trace ---
   at Xstream.Core.XStreamMarshaller.FromXml(String xml, IMarshalContext 
context)
   at Xstream.Core.XStream.FromXml(String xml)

Original issue reported on code.google.com by cgoudien...@gmail.com on 8 Oct 2009 at 7:33

GoogleCodeExporter commented 9 years ago
Here's a sample converter that makes this much prettier:

class HashtableConverter : IConverter
{
    private static readonly Type localType = typeof(Hashtable);

    public void Register(IMarshalContext context)
    {
        context.RegisterConverter(localType, this);
        context.Alias("hashtable", localType);
    }

    public void ToXml(object value, FieldInfo field, XmlTextWriter xml, 
IMarshalContext context)
    {
        Hashtable ht = value as Hashtable;
        Type hashtableType = ht.GetType();

        context.WriteStartTag(hashtableType, field, xml);

        int stackIx = context.GetStackIndex(value);

        if (stackIx >= 0)
            xml.WriteAttributeString("ref", stackIx.ToString());
        else
        {
            context.Stack(ht);

            foreach (object key in ht.Keys)
            {
                Entry hte = new Entry(key, ht[key]);
                IConverter converter = context.GetConverter(hte.GetType());

                if (converter == null) throw new Exception("Couldnot find converter 
for: " + hte.GetType() + " having value: " + hte);
                converter.ToXml(hte, null, xml, context);
            }
        }

        context.WriteEndTag(hashtableType, field, xml);
    }

    public object FromXml(object parent, FieldInfo field, Type type, XmlNode xml, 
IMarshalContext context)
    {
        Hashtable ht;

        if (xml.Attributes["ref"] != null)
        {
            int stackIx = int.Parse(xml.Attributes["ref"].Value);
            ht = context.GetStackObject(stackIx) as Hashtable;
        }
        else
        {
            int childCount = xml.ChildNodes.Count;
            ht = Activator.CreateInstance(type, new object[] { childCount, 1.0f }) as 
Hashtable;

            // Add the object to the stack
            context.Stack(ht);
            foreach (XmlNode child in xml.ChildNodes)
            {
                Type memberType = null;
                IConverter converter = context.GetConverter(child, ref memberType);

                Entry hte = (Entry)converter.FromXml(null, null, memberType, child, 
context);

                ht.Add(hte.key, hte.value);
            }
        }

        return ht;
    }
}

public class Entry
{
    public object key;
    public object value;

    public Entry(Object key, Object value)
    {
        this.key = key;
        this.value = value;
    }

    public string toString()
    {
        return "key: " + key + " value: " + value;
    }
}

Original comment by cgoudien...@gmail.com on 9 Oct 2009 at 9:59

GoogleCodeExporter commented 9 years ago
If you use he above converter, you should be able to serialize and deserialize 
hashtables with ease.

If you're using the current release (1.0) of the DLL and you would like to use 
this 
converter without modifying the source of XStream, here is how to get it into 
the 
converter list:

        XStream xs = new XStream();
        FieldInfo f = xs.GetType().GetField("context", BindingFlags.NonPublic | 
BindingFlags.Instance);
        IMarshalContext mc = (IMarshalContext)f.GetValue(xs);
        mc.RegisterConverter(typeof(Hashtable), new HashtableConverter());
        xs.Alias("entry", typeof(Entry));

Original comment by cgoudien...@gmail.com on 9 Oct 2009 at 10:02