views:

413

answers:

2

I understood that anonymous types are marked private by the compiler and the properties are read-only. Is there a way to serialize them to xml (without deserialize) ? It works with JSON, how can I do it with XML?

+2  A: 

Sorry, you cannot. The XML Serializer pretty much just serializes public read-write types.

John Saunders
That doesn't mean you can't do it with a third-party class, though.
Matthew Flaschen
is it possible to write something generic?
Radu
@Radu: I don't know what you mean "write something generic". Not if you're talking about using the XML Serializer. The answer from "Matthew Whited" shows you how to do this without using the XML Serializer.
John Saunders
@Downvoter: you would have a much greater impact if you gave your reasons for downvoting. I always do, and it really helps the answerer understand what he did wrong, and they often correct their problem. It's not possible to correct the problem you saw, because you haven't told us what the problem is.
John Saunders
It's probably one of the guys that downvotes all answers that don't get marked as the "correct" answer. Shame that people can't see that you are also correct in that the built-in xml serializer will not work.
Matthew Whited
+6  A: 

Something like this should get you started...

class Program
{
    static void Main(string[] args)
    {
        var me = new
        {
            Hello = "World",
            Other = new
            {
                My = "Object",
                V = 1,
                B = (byte)2
            }
        };

        var x = me.ToXml();
    }
}
public static class Tools
{
    private static readonly Type[] WriteTypes = new[] {
        typeof(string), typeof(DateTime), typeof(Enum), 
        typeof(decimal), typeof(Guid),
    };
    public static bool IsSimpleType(this Type type)
    {
        return type.IsPrimitive || WriteTypes.Contains(type);
    }
    public static XElement ToXml(this object input)
    {
        return input.ToXml(null);
    }
    public static XElement ToXml(this object input, string element)
    {
        if (input == null)
            return null;

        if (string.IsNullOrEmpty(element))
            element = "object";
        element = XmlConvert.EncodeName(element);
        var ret = new XElement(element);

        if (input != null)
        {
            var type = input.GetType();
            var props = type.GetProperties();

            var elements = from prop in props
                           let name = XmlConvert.EncodeName(prop.Name)
                           let val = prop.GetValue(input, null)
                           let value = prop.PropertyType.IsSimpleType()
                                ? new XElement(name, val)
                                : val.ToXml(name)
                           where value != null
                           select value;

            ret.Add(elements);
        }

        return ret;
    }
}

... resulting xml ...

<object>
  <Hello>World</Hello>
  <Other>
    <My>Object</My>
    <V>1</V>
    <B>2</B>
  </Other>
</object>
Matthew Whited
I guess `Type.IsValueType` could be a nice shortcut for most of the `IsAssignableFrom` s. Doesn't catch the `string` though.
Markus
`IsValueType` can be a wrong choice. This would use the ToString value to convert the type. But I have made a change that should be much easier to understand.
Matthew Whited