Tuesday, June 10, 2008
« My Vista Experience (thus far) | Main | CSLA .NET training in Dublin, Ireland »

I've been prototyping various aspects of CSLA Light (CSLA for Silverlight) for some time now. Enough to be confident that a decent subset of CSLA functionality will work just fine in Silverlight - which is very exciting!

The primary area of my focus is serialization of object graphs, and I've blogged about this before. This one issue is directly on the critical path, because a resolution is required for the data portal, object cloning and n-level undo.

And I've come to a final decision regarding object serialization: I'm not going to try and use reflection. Silverlight turns out to have some reasonable support for reflection - enough for Microsoft to create a subset of the WCF DataContractSerializer. Unfortunately it isn't enough to create something like the BinaryFormatter or NetDataContractSerializer, primarily due to the limitations around reflecting against non-public fields.

One option I considered is to say that only business objects with public read-write properties are allowed. But that's a major constraint on OO design, and still doesn't resolve issues around calling a property setter to load values into the object - because object setters typically invoke authorization and validation logic.

Another option I considered is to actually use reflection. I discussed this in a previous blog post - because you can make it work as long as you insert about a dozen lines of code into every class you write. But I've decided this is too onerous and bug-prone. So while reflection could be made to work, I think the cost is too high.

Another option is to require that the business developer create a DTO (data transfer object) for each business object type. And all field values would be stored in this DTO rather than in normal fields. While this is a workable solution, it imposes a coding burden not unlike that of using the struct concepts from my CSLA Classic days in the 1990's. I'm not eager to repeat that model...

Yet another option is to rely on the concept of managed backing fields that I introduced in CSLA .NET 3.5. In CSLA .NET 3.5 I introduced the idea that you could choose not to declare backing fields for your properties, and that you could allow CSLA to manage the values for you in something called the FieldManager. Conceptually this is similar to the concept of a DependencyProperty introduced by Microsoft for WF and WPF.

The reason I introduced managed backing fields is that I didn't expect Silverlight to have reflection against private fields at all. I was excited when it turned out to have a level of reflection, but now that I've done all this research and prototyping, I've decided it isn't useful in the end. So I'm returning to my original plan - using managed backing fields to avoid the use of reflection when serializing business objects.

The idea is relatively simple. The FieldManager stores the property values in a dictionary (it is actually a bit more complex than that for performance reasons, but conceptually it is a dictionary). Because of this, it is entirely possible to write code to loop through the values in the field manager and to copy them into a well-defined data contract (DTO). In fact, it is possible to define one DTO that can handle any BusinessBase-derived object, and other for any BusinessListBase-derived object and so forth. Basically one DTO per CSLA base class.

The MobileFormatter (the serializer I'm creating) can simply call Serialize() and Deserialize() methods on the CSLA base classes (defined by an IMobileObject interface that is implemented by BusinessBase, etc.) and the base class can get/set its data into/out of the DTO supplied by the MobileFormatter.

In the end, the MobileFormatter will have one DTO for each business object in the object graph, all in a single list of DTOs. The DataContractSerializer can then be used to convert that list of DTOs into an XML byte stream, as shown here:

image

The XML byte stream can later be deserialized into a list of DTOs, and then into a clone of the original object graph, as shown here:

image

Notice that the object graph shape is preserved (something the DataContractSerializer in Silverlight can't do at all), and that the object graph is truly cloned.

This decision does impose an important constraint on business objects created for CSLA Light, in that they must use managed backing fields. Private backing fields will not be supported. I prefer not to impose constraints, but this one seems reasonable because the alternatives are all worse than this particular constraint.

My goal is to allow you to write your properties, validation rules, business rules and authorization rules exactly one time, and to have that code run on both the Silverlight client and on your web/app server. To have that code compile into the Silverlight runtime and the .NET runtime. To have CSLA .NET and CSLA Light provide the same set of public and protected members so you get the same CSLA services in both environments.

By restricting CSLA Light to only support managed backing fields, I can accomplish that goal without imposing requirements for extra coding behind every business object, or the insertion of arcane reflection code into every business class.


Wednesday, June 11, 2008 4:04:44 AM (Central Standard Time, UTC-06:00)
Hi Rocky,

I've experienced a big performance drop (about 100% slower) when switching to managed fields. Is this normal or is there something I can do to improve the performance? I use a code generator to produce code with and without managed fields. I then create a large number of objects (in memory) and modify their properties. The code with managed fields is significantly slower.

Is it a possible solution that you do not restrict CSLA light to only support managed backing fields, but requires the BO that do not use it to override a method that returns a list of field values (simulating the dictionary of the backing fields). In this way you can use your own fields and still support the MobileFormatter. The code is easily created by a code generator anyway.

Anders Sidwall
Anders Sidwall
Wednesday, June 11, 2008 6:32:28 PM (Central Standard Time, UTC-06:00)
I am just thinking out loud. And, I have yet adopted version 3.5. Anyway, I think by restricting CSLA Light objects to only managed fields might have negative concerns. For example, it is quite common for a collection to maintain its own private dictionary of mapped objects for fast lookup, which is not being managed by the framework.
William
Wednesday, June 11, 2008 9:26:18 PM (Central Standard Time, UTC-06:00)
Anders, I think we've arrived at a solution where managed fields will be serialized automatically, and you'll be able to manually put arbitrary values into the serialization stream as well, and get them back out of course.

You could use the reflection scheme I blogged about (and rejected) earlier. Or you could manually write one line of code per field for serialization and one per field for deserialization. And of course you could code-gen that code.

This also addresses William's concern - I don't want to block adoption because of managed fields - but without reflection there's no good automated alternative - so if you really want to use private backing fields we'll allow it, you'll just have to do some work and maintain some code.
Thursday, June 12, 2008 2:40:31 AM (Central Standard Time, UTC-06:00)
That seems like a good solution.

Anders Sidwall
Anders Sidwall
Comments are closed.