Coffeehouse Thread

13 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

XAML serialization

Back to Forum: Coffeehouse
  • User profile image
    exoteric

    It's a mystery to me why XAML wohn't serialize my objects unless the classes have default constructors and why properties wohn't be serialized unless there are setters for the properties. I understand why XAML can't necessarily deserialize instances of such unhelpful classes but the other way around is completely mystifying to me. Zero-parameter constructors also breaks the contract for the class as objects are not properly initialized, hence violating the class invariant.

     

    That said, XAML is very nice and a very easy way to serialize objects. I just wish it wouldn't force me to break my class invariants or at least not for serialization scenarios. So I guess until this is fixed my XLinq query will have to do - which in fairness is very succint, it's just that a XAML alternative would be perfect for prototyping and initial debugging.

     

    This way of handling object initialization is also at odds with an invariant-style programming where objects are constants. I don't have an answer to pull out of my sleeve but some thought should be put into this.

  • User profile image
    figuerres

    did you mean XML ??

    are you talking about XAML in memory ??  to save to disk?

     

     

  • User profile image
    Dr Herbie

    I expect that the framework designers (not unreasonaby) assumed that if you were serialising a class, you would be expecting to deserialise it as well, so they make the rules based on that assumption.

     

    Herbie

     

  • User profile image
    exoteric

    figuerres said:

    did you mean XML ??

    are you talking about XAML in memory ??  to save to disk?

     

     

    I did not mean XML per se, I meant the XML Application Markup Language (XAML) (which is now a little bit at odds with its roots as it "can" now detach itself from its XML serialization). The precise API call is this

     

    XamlServices.Save(module);

     

    This call just "saves" to a string.

     

    The first thought that hit me was: I probably need to decorate my classes with serialization helper attributes but then I googled a little and found out that apparently it's a requirement that a class be deserializable in order to serialize it. The XAML stack appears to enforce "roundtripability".

     

    As an aside, it may be interesting if the API also deployed a pull-based model, returning a Stream. And as an aside from even that, why don't we have LINQ to streams? heh

  • User profile image
    PerfectPhase

    Coming soon in XAML-2009 non-default constructors....

     

    <coll:List x:Key='list' x:TypeArguments='x:String' x:FactoryMethod='local:Factory.CreateStringList'>

        <x:Arguments>

            <x:String>Mickey,Donald</x:String>

        </x:Arguments>

    </coll:List>

     

    via: http://blogs.msdn.com/llobo/archive/2009/11/20/xaml-2009-features-factorymethod-arguments.aspx

     

    You might want to have a look at the noode stream support in System.Xaml (see PDC2008 - TL36)  You can proberbly do what ever you like if you use XamlObjectReader and XamlXmlWriter rather than XamlServices.

  • User profile image
    exoteric

    Dr Herbie said:

    I expect that the framework designers (not unreasonaby) assumed that if you were serialising a class, you would be expecting to deserialise it as well, so they make the rules based on that assumption.

     

    Herbie

     

    I don't think this is a reasonable assumption to make. "Sorry bro, I can't read this for you because you're not providing me with write access"; Say what? I don't think framework designers should ever wire in prohibitive assumptions that prevent reasonable use-cases of the framework.

     

    The assumption is not that the output be deserialized, it is (more or less) that it be deserialized by the current XAML stack which by nature requires some conventions to be followed in order to work in a generic wayThis assumption is unreasonable and goes against XML design principles of openness; of course the output XML is open enough per se, it just wohn't happen unless you change your class invariant.

  • User profile image
    exoteric

    PerfectPhase said:

    Coming soon in XAML-2009 non-default constructors....

     

    <coll:List x:Key='list' x:TypeArguments='x:String' x:FactoryMethod='local:Factory.CreateStringList'>

        <x:Arguments>

            <x:String>Mickey,Donald</x:String>

        </x:Arguments>

    </coll:List>

     

    via: http://blogs.msdn.com/llobo/archive/2009/11/20/xaml-2009-features-factorymethod-arguments.aspx

     

    You might want to have a look at the noode stream support in System.Xaml (see PDC2008 - TL36)  You can proberbly do what ever you like if you use XamlObjectReader and XamlXmlWriter rather than XamlServices.

    This is great news PerfectPhase! It would be really great if it also meant that setters could be by-passed entirely.

  • User profile image
    Rob Relyea

    PerfectPhase said:

    Coming soon in XAML-2009 non-default constructors....

     

    <coll:List x:Key='list' x:TypeArguments='x:String' x:FactoryMethod='local:Factory.CreateStringList'>

        <x:Arguments>

            <x:String>Mickey,Donald</x:String>

        </x:Arguments>

    </coll:List>

     

    via: http://blogs.msdn.com/llobo/archive/2009/11/20/xaml-2009-features-factorymethod-arguments.aspx

     

    You might want to have a look at the noode stream support in System.Xaml (see PDC2008 - TL36)  You can proberbly do what ever you like if you use XamlObjectReader and XamlXmlWriter rather than XamlServices.

    @exoteric-

    You can work with Non-Default Constructors

    XamlServices.Save() in .Net 4 can write instances which need non-default constructors to be created. In order to tell the Save() routine (or really the XamlObjectReader under the covers) which constructor to use, you must have a TypeConverter or ValueSerializer that can return an InstanceDescriptor given the instance.

     

    RoundTripping

    Yes, XamlServices.Save() currently attempts to only ever write things that can be read. Would love to understand what properties you want to write, and why. Do you intend to try to read them later?

    PerfectPhase mentions using XamlObjectReader and XamlXmlWriter and added the functionality you want.  XamlObjectReader has an Instance property, which should enable you to see the current object that the XOR is dealing with...perhaps you could inject additional XAML nodes via a XAML node loop.

     

    Ways that WPF has dealt with default Constructors and immutability

    In WPF, some types inherit from Freezable which enables a pattern of r/w properties until they Freeze() is called, then they throw if you try to set them.

     

    Hope that helps. Look forward to more feedback/discussion.

     

    Thanks,

    Rob Relyea

    XAML Team

    http://robrelyea.com/blog

  • User profile image
    exoteric

    Rob Relyea said:
    PerfectPhase said:
    *snip*

    @exoteric-

    You can work with Non-Default Constructors

    XamlServices.Save() in .Net 4 can write instances which need non-default constructors to be created. In order to tell the Save() routine (or really the XamlObjectReader under the covers) which constructor to use, you must have a TypeConverter or ValueSerializer that can return an InstanceDescriptor given the instance.

     

    RoundTripping

    Yes, XamlServices.Save() currently attempts to only ever write things that can be read. Would love to understand what properties you want to write, and why. Do you intend to try to read them later?

    PerfectPhase mentions using XamlObjectReader and XamlXmlWriter and added the functionality you want.  XamlObjectReader has an Instance property, which should enable you to see the current object that the XOR is dealing with...perhaps you could inject additional XAML nodes via a XAML node loop.

     

    Ways that WPF has dealt with default Constructors and immutability

    In WPF, some types inherit from Freezable which enables a pattern of r/w properties until they Freeze() is called, then they throw if you try to set them.

     

    Hope that helps. Look forward to more feedback/discussion.

     

    Thanks,

    Rob Relyea

    XAML Team

    http://robrelyea.com/blog

    Thanks for the answer Rob. I'll go read how these type converters work.

     

    The reason I care about this is that 1) the classes are supposed to be invariant, they're designed this way; 2) XAML is actually a great way to quickly debug your code by dumping out an object graph; I'm projecting binary files into an object graph and want to verify that the projection is not completely foobar; XAML is actually quite nice in this regard - it's also possible to toss out some data to some folks who can then possibly use XSLT, XLinq and whatnot to do further processing on the data - maybe injecting it into a SQL store and whatnot - without needing my code (although the code is freely available.)

     

    I guess my reason for disliking the settability requirement is because it forces me to abandon a declarative/functional style of programming. I want to maximize the compiler's (hypothetical) ability to perform optimizations without needing too much analysis and to have strong guarantees about how the data can be used ("reuse":projection over "use":mutation). This is somewhat a purist stance but it is actually reasonable to not want to have classes have the property of mutability. The WPF freezable properties is pretty nice but I prefer static guarantees whenever possible; I don't want any code to even try and attempt to modify the data; or more precisely, I don't want any codepath to have this possibility. I'll admit that these design principles are overkill for the hobby framework I'm building but I believe they are quite sound in general.

     

    It's pretty cool that XAML can project (almost) any object graph to X(A)ML with just one line of code; it's an extremely quick and easy way to generate data, even if for prototyping or analysis purposes.

     

    That being said, you could of course argue that my use-case is silly and I should simply use XLinq projection for this - it's just that this is a use-case XAML could (it appears) easily support with no downsides. I suppose the reasoning behind the design may also be to help developers in their class design so that they can read in the data again

     

    I wonder if someone should build static analysis for this situation as well and just warn in this case; maybe the Load method should have a type-parameter as well to make it easier to tell, in case the cast doesn't happen right away. Maybe put a "XamlReady" attribute on the classes.

  • User profile image
    Rob Relyea

    exoteric said:
    Rob Relyea said:
    *snip*

    Thanks for the answer Rob. I'll go read how these type converters work.

     

    The reason I care about this is that 1) the classes are supposed to be invariant, they're designed this way; 2) XAML is actually a great way to quickly debug your code by dumping out an object graph; I'm projecting binary files into an object graph and want to verify that the projection is not completely foobar; XAML is actually quite nice in this regard - it's also possible to toss out some data to some folks who can then possibly use XSLT, XLinq and whatnot to do further processing on the data - maybe injecting it into a SQL store and whatnot - without needing my code (although the code is freely available.)

     

    I guess my reason for disliking the settability requirement is because it forces me to abandon a declarative/functional style of programming. I want to maximize the compiler's (hypothetical) ability to perform optimizations without needing too much analysis and to have strong guarantees about how the data can be used ("reuse":projection over "use":mutation). This is somewhat a purist stance but it is actually reasonable to not want to have classes have the property of mutability. The WPF freezable properties is pretty nice but I prefer static guarantees whenever possible; I don't want any code to even try and attempt to modify the data; or more precisely, I don't want any codepath to have this possibility. I'll admit that these design principles are overkill for the hobby framework I'm building but I believe they are quite sound in general.

     

    It's pretty cool that XAML can project (almost) any object graph to X(A)ML with just one line of code; it's an extremely quick and easy way to generate data, even if for prototyping or analysis purposes.

     

    That being said, you could of course argue that my use-case is silly and I should simply use XLinq projection for this - it's just that this is a use-case XAML could (it appears) easily support with no downsides. I suppose the reasoning behind the design may also be to help developers in their class design so that they can read in the data again

     

    I wonder if someone should build static analysis for this situation as well and just warn in this case; maybe the Load method should have a type-parameter as well to make it easier to tell, in case the cast doesn't happen right away. Maybe put a "XamlReady" attribute on the classes.

    @exoteric-

    I think I understand your scenarios for XAML:

    1) Want immutable types.

    • Hope that the immutability part can work with non-default constructors for you.

    2) Want to write down most of the state of the object

    • What rules would be ideal for you? Some R/O properties (like a parent pointer, get a bit tricky). We use DesignerSerializationVisibilityAttribute to Hide some properties that would normal be written. In your scenario, please review all R/O properties, and see what rules would work for you.
    • If you look at http://robrelyea.com/demos/xamlpadsample and the way I write down Pad.config.xaml, you'll see that I'm using XAML for a similar purpose...and it is helpful during development/debugging. I'm also focusing on using that file for config settings, so I'm sticking to normal rules for which properties get written, as I am going to load it later.

    Thanks, Rob

     

  • User profile image
    exoteric

    Rob Relyea said:
    exoteric said:
    *snip*

    @exoteric-

    I think I understand your scenarios for XAML:

    1) Want immutable types.

    • Hope that the immutability part can work with non-default constructors for you.

    2) Want to write down most of the state of the object

    • What rules would be ideal for you? Some R/O properties (like a parent pointer, get a bit tricky). We use DesignerSerializationVisibilityAttribute to Hide some properties that would normal be written. In your scenario, please review all R/O properties, and see what rules would work for you.
    • If you look at http://robrelyea.com/demos/xamlpadsample and the way I write down Pad.config.xaml, you'll see that I'm using XAML for a similar purpose...and it is helpful during development/debugging. I'm also focusing on using that file for config settings, so I'm sticking to normal rules for which properties get written, as I am going to load it later.

    Thanks, Rob

     

    My use-case is very simple. I have no private properties and all public properties should be written out - nothing to hide if you will. So you're right, I want to write it all out. Immutable types because they're far easier to reason about. I could imagine cases where it would be required to not write out certain properties but it's a non-issue for my trivial scenario. I'll definitely use the non-default constructor approach now. The below illustrates the motivation further, heh -

     

    The fundamentalist and the minimalist:

        "XLinq is superb - what could possibly be better than writing an XLinq query?"
        "- Not writing one"

  • User profile image
    Dan Glick

    exoteric said:
    Rob Relyea said:
    *snip*

    My use-case is very simple. I have no private properties and all public properties should be written out - nothing to hide if you will. So you're right, I want to write it all out. Immutable types because they're far easier to reason about. I could imagine cases where it would be required to not write out certain properties but it's a non-issue for my trivial scenario. I'll definitely use the non-default constructor approach now. The below illustrates the motivation further, heh -

     

    The fundamentalist and the minimalist:

        "XLinq is superb - what could possibly be better than writing an XLinq query?"
        "- Not writing one"

    As Rob said, if your classes are immutable, then the default XAML binding won't be useful even if they have default constructors, because we don't write out read-only properties (except for collections).

     

    Fortunately, you can change the default XAML binding. Override XamlSchemaContext.GetXamlType, and return your own class derived from XamlType. There you can override LookupIsDefaultConstructible (always return true) and LookupMember (return an overriden XamlMember which always returns false for LookupIsReadOnly). That should cause XAML to dump out immutable classes.

     

    I have a couple of samples of overriding XamlSchemaContext in my blog at http://blogs.msdn.com/dglick/; if I get time I'll post an example of this.

  • User profile image
    exoteric

    Dan Glick said:
    exoteric said:
    *snip*

    As Rob said, if your classes are immutable, then the default XAML binding won't be useful even if they have default constructors, because we don't write out read-only properties (except for collections).

     

    Fortunately, you can change the default XAML binding. Override XamlSchemaContext.GetXamlType, and return your own class derived from XamlType. There you can override LookupIsDefaultConstructible (always return true) and LookupMember (return an overriden XamlMember which always returns false for LookupIsReadOnly). That should cause XAML to dump out immutable classes.

     

    I have a couple of samples of overriding XamlSchemaContext in my blog at http://blogs.msdn.com/dglick/; if I get time I'll post an example of this.

    Sounds good Dan. I'll create a XamlSchemaContext and see how that works out for me.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.