I just ran into another feature whose absence from Silverlight is sorely missed.
I’m using the WCF generated proxy classes as the basis for binding to some UI objects. If you’re using a full MVVM pattern, the way that you’d normally do this is wrap the proxy-generated classes with a ViewModel, so that instead of binding to, say, the User class generated by “Add Service Reference”, you’d bind to a UserViewModel class that acts as a facade for the User class. So far, I haven’t been willing to go that route. The only point to having a ViewModel is if you’re making extensive use of databinding, and databinding happens to be my least favorite Silverlight technology, for reasons that I’ve explained elsewhere. And if I’m only doing databinding occasionally, it seems like a lot of more-or-less pointless work to recreate a facade for my complete object model on the client, and then keep it synchronized with the classes that the Entity Framework has already helpfully generated for me. So I’ve been making do with partial classes to add any additional properties or methods that seem appropriate.
But as I said, I ran into a problem today. One of my classes, SharedFile, has a bindable property called StatusText whose value depends on a complicated graph of other object properties; and to get them all working, I’ve had to string together an unpleasant chain of INotifyPropertyChanged notifications, sorta like so (this is just one of numerous chained handlers):
OK, so far so good – but I have to wire up these event handlers somewhere. Since the definition of SharedFile in reference.cs didn’t define a default constructor, I thought it would be simple to create one in my partial class, and that would be the end of it:
But although the objects get created, that constructor never gets called. WTF? Well, it turns out that when Silverlight deserializes the XML from my WCF service, it uses FormatterServices.GetUninitializedObject to create the object, which skips calling the constructor. I guess that makes a certain sort of sense – the WCF service is handing you an object that, in theory, is already constructed, so you shouldn’t need to call the constructor again. I get that. But then where do I put this code?
I get that some features need to be left out of Silverlight. But this seems like a really odd one. Serializing and deserializing objects is what you do in Silverlight. You can write real-world WPF or WinForm or ASP.NET applications all day long and never once have to deal with object serialization and deserialization. But you can’t use Silverlight for five minutes without needing to touch an object that’s just been deserialized from some web service. So why choose that particular set of features to cut? It sure seems like a bizarre design choice.
At any rate, my choices were either to implement a full-blown ViewModel layer, which I really don’t want to do, or write a hack of some sort to initialize the event handlers manually. Uggh.
What I’ve done for now is to throw an Initialize() method on the containing object (User), which in turn initializes any object that gets added to its SharedFiles ObservableCollection:
And then I call User.Initialize() when I first retrieve it from the web service:
Like I said, uggh. But it works. I just wish that MS had thought through their deserialization scenarios a little better. I don’t like being forced into creating another abstraction layer if I don’t have to.