views:

84

answers:

3

Following on from a previous question, I am having trouble combining the Lazy<T> generic that was suggested with my XML Serialization.

Here is the functionality I am using for Lazy<T>:

public struct Lazy<T> where T : class, new()
{
    private T _Value;

    public bool HasValue
    {
        get
        {
            return (_Value != null);
        }
    }

    public T Value
    {
        get
        {
            if (!HasValue)
                _Value = new T();

            return _Value;
        }
    }
}

Now the MSDN Docs say that it's fine to have an [XmlElement("ElementName")] on a property and it does indeed seem to be able to deserialize just fine. The problem comes when I am serializing an object. I am running the following piece of code:

class SomeClass
{
    [XmlElement("ExternalElementName")]
    public ComplexElementType InternalElementName
    { 
        get { return _InternalElementName.Value; } 
    }

    protected Lazy<ComplexElementType> _InternalElementName;
}

Elsewhere:

SomeClass someClass = new SomeClass();
someClass.InternalElementName.ComplexElementTypeChild = "some string";

// serialize...

The strange thing is, this works fine in the debugger but no element is output in the XML. Non Lazy<T> elements work fine. Any ideas?

A: 

Not sure what the problem is (I have always found the XML serializer behaviour to be shifty), but why not use the Nullable<T> class? Don't re-invent the wheel :)

Aistina
I'm not quite following where I would use Nullable<T>?
Nat Ryall
Wherever you currently use Lazy<T>. I'm pretty sure the behaviour is exactly the same, although Nullable<T> also supports basic types such as int or bool.
Aistina
Value in Lazy<T> creates an instance if one doesn't exist - Nullable<T> throws an exception. :)
Nat Ryall
+3  A: 

The problem is that the property has no setter. Even if it would be possible to get the value to serialise it, it can't be deserialised as there is no way to put the value back in the new object.

Guffa
Deserialising of the object works, but that's just because the property is not included when serialised. Deserialising the property doesn't work, so it's not included when the object is serialsed. The property needs a setter so that it can be deserialised for it to be included when serialsed.
Guffa
This is being serialised from a new object so I am confused as to why this worked. I would have thought serialising wouldn't have needed a setter.
Nat Ryall
The serialisation itself doesn't need the setter, but it won't include properties that it knows are impossible to deserialise.
Guffa
+1  A: 

By design, XML Serialization will only serialize public read/write properties, and public fields.

John Saunders