Tuesday, July 15, 2008

I have put a very early preview release of CSLA Light and CSLA .NET 3.6 online at www.lhotka.net/cslalight/download.aspx.

There is no sample app at this point, so you'll have to look at the unit tests in cslalighttest and cslatest to figure out how to use the various features.

Obviously this is very early code, but it is healthy to release early and often, so here we go :)

One side-effect of our work with CSLA Light is that we discovered that testing asynchronous methods is really hard with nunit and MSTest, and impossible with the Silverlight unit test framework provided by Microsoft. And yet in Silverlight, async methods are commonly required, and for parity a number of async features are now also in CSLA .NET. And we need to have unit tests for them.

To address this issue, we ended up creating our own Silverlight unit testing framework, and an add-on framework for nunit or MSTest. This allows us to write a common set of test code that runs in both Silverlight and .NET so we can test both, and establish that we have parity between them.

Earier today, Justin split this testing framework out of CSLA and we put it up on CodePlex, calling it UnitDriven. The CSLA Light project and Magenic are donating the code to the community as an open-source project, because it can be used to build async unit tests for any app, not just for CSLA Light.

Tuesday, July 15, 2008 6:40:52 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  | 

I get a lot of questions about Expert 2008 Business Objects as to what it will and won't cover, so I thought I'd try and answer at least some of them in a blog post.

The book will cover CSLA .NET 3.6. Version 3.6 is the same as 3.5, but with support for CSLA Light and some .NET 3.5 SP1 features (such as the Entity Framework). And along with CSLA Light comes some interesting support for things like an async data portal and async validation rules. But please note that this book will not cover CSLA Light - that's a book by itself, believe me!

Here's the tentative table of contents for the book:

1.     Architecture

2.     Design

3.     Object-oriented design

4.     Supported stereotypes

5.     Stereotype templates

6.     Framework Implementation

7.     Editable Objects and Collections

8.     Data Binding

9.     Business and Validation Rules

10.   Authorization Rules

11.   N-level Undo

12.   LINQ to CSLA

13.   Persistence and the Data Portal

14.   Other Framework Features

15.   Example Business Library

16.   WPF Application

17.   Web Forms Application

18.   WCF Service Application

The items in green are complete - first draft anyway - and so you can get an idea where I am in the process.

Due to space and time constraints, this book will have three UI chapters just like the previous books. So I had to choose which interface technologies to cover - out of the myriad options available:

  • WPF
  • WPF/XBAP
  • Windows Forms
  • asmx services
  • WCF services
  • WF workflows and activities
  • ASP.NET Web Forms
  • ASP.NET MVC
  • Office/VSTO (Word, Excel, etc)
  • Console

I want to make sure to cover smart clients, web development and services. While WCF and Web Forms were easy choices (though I do like ASP.NET MVC a lot, it isn't mainstream yet), the choice between Windows Forms and WPF was difficult. But I have to give WPF the nod, because it is a really nice technology, and it really shows off the power of CSLA .NET business objects very nicely.

My current plan is to release ebooks that specifically focus on each of the interface technologies not covered in Expert 2008 Business Objects, and some sort of book (ebook or traditional) covering CSLA Light.

Tuesday, July 15, 2008 9:17:28 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [7]  | 

 Monday, July 14, 2008

While most people use CSLA .NET because it provides support for data binding, validation, business rules and authorization, I personally think the coolest part of the framework is its support for mobile objects. This support is provided by the data portal, which provides both an abstract persistence model for business objects, as well as an implementation of mobile objects with location and network transparency.

CSLA Light will also include a data portal that works in a manner similar to the one in CSLA .NET. In fact, the two are complimentary - the CSLA Light data portal talks to the CSLA .NET data portal, because the client is running Silverlight and the server is running .NET. This occurs when the CSLA Light data portal is running in "remote" mode - meaning it is talking to a remote data portal server.

The CSLA Light data portal can also run in "local" mode, which means that the "data access" code runs on the Silverlight client. In reality, this probably means that your client-side code is directly calling some external service - an asmx web service, a WCF service, ADO.NET data services, etc. So the fact is that the data access is still on some server somewhere, but you aren't using the data portal to get from the client to that server.

As in .NET, when using the data portal in local mode things are pretty simple. A call to the data portal to fetch an object simply results in a call to a DataPortal_Fetch() method in your object, and the object is running on the client in Silverlight. What you do in that DataPortal_Fetch() method is entirely up to you, as long as the object is populated with data by the time the call completes.

When you use the remote data portal there are more options. Things are somewhat different from the existing .NET data portal. The following figure will help explain.

image

The CSLA Light data portal interacts with a server (probably a web server, though it could be a Windows Server 2008 running WAS) through WCF. That server is running CSLA .NET 3.6, which includes data portal support to listen for CSLA Light data portal requests. Objects are serialized to/from CSLA Light using the MobileFormatter, which is a serializer included in both CSLA Light and CSLA .NET that provides a subset of the functionality provided by the BinaryFormatter (or NetDataContractSerializer), targeted at the CSLA scenario.

On the web server, CSLA .NET 3.6 receives the inbound client request. Any objects sent from the client to the server are deserialized (including any criteria objects or business objects). At this point there are two ways the process will work.

The default option is that the call from the client is "echoed" into the standard CSLA .NET data portal. In other words, if the client calls Fetch() on the data portal, that call is relayed into the standard data portal as a Fetch() request. This means that the .NET data portal applies its normal process and runs in local or remote mode and ultimately creates an instance of your business object and calls its DataPortal_Fetch() method. Remember that this is all happening in .NET on the server(s). The resulting business object is then returned through the .NET data portal to the web server, and from there through the Silverlight data portal to the client.

So by default, the .NET data portal running on the web server (in the diagram) is a pass-through from Silverlight into .NET. The end result is that the Silverlight data portal works just like the .NET data portal does today.

While the default is good and easy, it may not always be ideal. You may not trust the code running in Silverlight on the client. You may be concerned that the code has been compromised, that somehow a malicious user cracked into the Silverlight runtime, mucked around with your code and bypassed your logic. Thus far no one has established that this can be done, but I can understand the concern.

In that case, another option is that the business class (on the .NET side) can have a MobileFactory attribute attached:

[MobileFactory("MyLibrary.CustomerFactory,MyLibrary", "Create", "Fetch", "Update", "Delete")]
public class Customer : BusinessBase<Customer>

If this attribute is applied, the .NET data portal will create an instance of the type specified in the attribute, and will call methods on that factory object instead of on the business object. In other words, a call that would have gone to DataPortal_Fetch() will now go to a method matching the third parameter of the attribute - in this example a method called Fetch().

The factory object is responsible for creating, initializing and returning the object from create/fetch/update operations. Delete returns nothing. How the factory object does this is up to the factory author - you. I suspect a very common implementation will be for the factory method to do extra business checks (validation/authorization) to decide if the client call is valid, and if it is valid then the factory will just echo the call into the .NET data portal. So you might write something like this in a factory:

public object Fetch(SingleCriteria<Customer, int> criteria)
{
  // do extra validation/authorization checks here
  if (allChecksPassed)
    return DataPortal.Fetch(criteria);
  else
    throw new Exception("Bad client request");
}

A colleague of mine at Magenic, Nermin Dibek, suggested an interesting enhancement to this MobileFactory model, which I'll include in the implementation. As a configuration option, you can specify a "factory of factories" object. The default behavior is to take the type name in the first parameter and use it to create an instance of the factory object. But if you'd like, you can create your own "factory creator" object that takes that first parameter and uses it however you'd like to create an instance of the factory. This would allow you to substitute MyTestLibrary for MyLibrary when you wanted to use a set of test factories instead of the production versions, and that sort of thing.

It is my intent to extend this MobileFactory concept into the .NET data portal itself (in CSLA .NET 3.6), so in a pure-.NET scenario you'd have comparable options, like this figure:

image

The data portal would default to its existing behavior, which would be unchanged. However, you'd be able to apply an ObjectFactory attribute to your business classes to indicate that the data portal should route its calls to your factory object rather than to the DataPortal_XYZ methods.

The only catch here, is that your factory objects then assume responsibility for managing the status values (IsNew, IsDirty, etc) of the object (and its child objects, etc). The data portal essentially steps out of the picture entirely - leaving you to do all the work of creating and manipulating the business object as necessary. However, this does open up some interesting alternatives for persisting objects even though the solution is less automated than the current implementation.

The CSLA Light part of what I've discussed here is in the current 3.6 code in Subversion (svn://svn.lhotka.net/csla/branches/cslacs36 and svn://svn.lhotka.net/csla/trunk/cslalightcs). The ObjectFactory support for CSLA .NET itself will probably happen in a few weeks.

Monday, July 14, 2008 9:41:52 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  | 

 Tuesday, June 24, 2008

With serialization largely out of the way - or at least under control - as described in a recent blog post, we've been able to put some focus on a couple other key areas.

N-Level Undo

The n-level undo functionality in CSLA .NET relies on reflection against private fields. Obviously that's not possible in Silverlight. Fortunately the serialization scheme we're using means that there's already a mechanism for trapping the values stored in the field manager. And there's the OnGetState()/OnSetState() methods that allow a business developer to trap/restore values in their private fields (if they choose). So UndoableBase had to be altered to use these techniques rather than using reflection. The end result is the same, which is what really matters.

We opted not to replicate IEditableObject into CSLA Light. It is a .NET interface used by Windows Forms data binding, and is the source of never-ending pain thanks to all the edge cases and idiosyncrasies around this, seemingly simple, interface. Of course the interface isn't used by Silverlight (or WPF), and so isn't necessary. The effect of this choice is to simplify quite a bit of the n-level undo code, while at the same time preserving the shape of the pre-existing public interface for all objects. In other words, BeginEdit(), CancelEdit() and ApplyEdit() work as expected, but you can't use IEditableObject to get at its versions of those methods.

Justin just ran into a strange issue with BusinessListBase, where an attempt to iterate through the items in the list caused a strange runtime exception from somewhere deep in the bowels of the Silverlight runtime. It appears there's some issue with a subclass of a collection iterating through its own items in a foreach loop. A for loop works fine however, so we have a workaround.

Ultimately however, the ability to easily implement a Cancel button, including when using modal dialogs (which can be simulated in Silverlight) is supported

Data Portal

The data portal is coming along pretty well too. It supports a provider model, conceptually similar to the data portal in .NET. And we currently have two providers: local and WCF.

One issue we're facing here is that Silverlight has no configuration subsystem comparable to System.Configuration. So there's no easy way to get configuration data from an "app.config" file or equivalent. At the moment I've come up with a code-based configuration scheme - but (unless Microsoft puts out a solution soon) we'll probably end up creating some embedded resource-based configuration subsystem of our own.

The data portal itself is asynchronous. This changes the way the UI code interacts with the data portal when compared to .NET code. Rather than just calling DataPortal.Fetch() to get an object, in Silverlight the UI must call a BeginFetch() method to start the process and handle a completed event to process any results when they return.

This means the UI code looks something like this:

var dp = new DataPortal<MockEditableRoot>();
dp.FetchCompleted += new EventHandler<DataPortalResult<MockEditableRoot>>(dp_FetchCompleted);
dp.BeginFetch();

This code starts the process, and the dp_FetchCompleted is invoked (on the UI thread) when the call is complete:

private void dp_FetchCompleted(object sender, DataPortalResult<MockEditableRoot> e)
{
  this.DataContext = e.Object;
}

Alternately you can wrap this code into a factory method and completed event provided by the business class. That is a little closer to the typical CSLA .NET model - but is still async, and the UI still must handle the result in a callback event handler.

Local Data Portal

When using the data portal in local mode, it calls DataPortal_XYZ methods, much like the .NET data portal. There are a couple interesting differences however. The first being that the DataPortal_XYZ methods must be public in scope. Remember, no private reflection, so only public methods can be called.

I debated about using an interface-based approach, but decided against it for a couple reasons. First, it would be dissimilar to the existing .NET approach. Second, it would mean that your DataPortal_XYZ methods couldn't be strongly typed - they'd have to accept parameters of type object and you'd have to cast them to something meaningful.

The second difference flows from the fact that most server-related activities in Silverlight are asynchronous. Most DataPortal_XYZ methods, therefore, will be invoking async server calls and getting the results from a callback event. So all DataPortal_XYZ methods are provided a delegate they can use to do a callback to indicate completion. In a simple (synchronous) example it looks like this:

public void DataPortal_Insert(
  Csla.DataPortalClient.LocalProxy<MockEditableRoot>.CompletedHandler handler)
{
  LoadProperty<string>(DataPortalMethodProperty, "insert");
  handler(this, null);
}

The DataPortal_Insert() method accepts a CompletedHandler parameter it can use to indicate completion. The call to handler() is the completion call, and the first parameter is the resulting business object, while the second is an Exception object if you want to indicate failure.

In an asynchronous example things are a bit more complex. And the async scenario is the most common. Typically when using a "local" data portal you'd be doing so because you want to call some web service or data service from Silverlight. And since all the server call technologies in Silverlight are async, your DataPortal_XYZ method will almost certainly be invoking some async service. So more normal code might look like this:

public void DataPortal_Insert(
  Csla.DataPortalClient.LocalProxy<MockEditableRoot>.CompletedHandler handler)
{
  var svc = new Csla.Testing.Business.TestService.TestServiceClient();
  svc.InsertDataCompleted +=
    new EventHandler<Csla.Testing.Business.TestService.InsertDataCompletedEventArgs>
      (svc_InsertDataCompleted);
  svc.InsertData(GetProperty<string>(DataPortalMethodProperty), handler);
}

void svc_InsertDataCompleted(
  object sender, Csla.Testing.Business.TestService.InsertDataCompletedEventArgs e)
{
  var handler = (Csla.DataPortalClient.LocalProxy<MockEditableRoot>.CompletedHandler)e.UserState;
  handler((MockEditableRoot)e.Result, e.Error);
}

This looks a bit odd, but after you do a bit of Silverlight programming this pattern becomes second nature.

The DataPortal_XYZ method sets up and starts the call - passing parameters to the service, and one parameter that is "user state", which is extra (doesn't go to the server, but stays on the client). Notice that before making the InsertDataAsync() call, which is the call to the service, the code hooks the InsertDataCompleted event - this is the event that will be raised (on the UI thread) when the service call completes.

The svc_InsertDataCompleted() method is the event handler. This is where you write the code to handle the results from the service call. When using the data portal, this is where you call back into CSLA to indicate that the call is complete. Ultimately CSLA will return the result to the UI code, but this mechanism allows CSLA to do any extra processing between the DP_XYZ call and the UI so it can manage the state of your business object.

You can also shrink this by using a lambda:

public void DataPortal_Insert(
  Csla.DataPortalClient.LocalProxy<MockEditableRoot>.CompletedHandler handler)
{
  var svc = new Csla.Testing.Business.TestService.TestServiceClient();
  svc.InsertDataCompleted += (o, e) => { handler((MockEditableRoot)e.Result, e.Error); };
  svc.InsertDataAsync(GetProperty<string>(DataPortalMethodProperty));
}

That eliminates the need for a separate event handler method and simplifies the code.

Remote Data Portal

The remote data portal option works very much like the normal .NET data portal, and is generally simpler to use that the local data portal. When the data portal is configured to use the WcfProxy, it will use WCF to communicate with a CSLA .NET data portal on the web/app server.

In this scenario you need a web or app server that is hosting a CSLA .NET data portal - the .NET end of the CSLA Light data portal. The CSLA Light code running on the Silverlight client will call the CSLA .NET code running on the app server.

When using a remote data portal, the Silverlight business object will not include any DataPortal_XYZ methods. The DataPortal_XYZ methods will only be implemented in the .NET code, and will only exist on the server. The client-side code will still call the data portal, but the call will be automatically routed through WCF to the app server.

This is exactly the same kind of behavior you'd get from the existing .NET data portal - you can choose to use a local or remote data portal, but the business object and UI code are the same either way (with the exception that a local data portal requires implementation of DataPortal_XYZ methods).

On the app server, which is running CSLA .NET, requests will come in from the Silverlight client. These requests can be handled in one of two ways.

The default is for the client call to be routed into the CSLA .NET data portal, and the rest of the processing is normal CSLA .NET processing. In other words, a Silverlight Fetch() call results in a DataPortal.Fetch() call on the app server, which runs the DataPortal_Fetch() method just like it always has. The result of the data portal call on the app server is then returned to the Silverlight client.

I call that the "pass-through" mode because the server-side data portal just passes the client call through to the "real" data portal. And this is a great option for when you trust the client that is running the Silverlight app, because it requires the least amount of code and provides the simplest solution.

But if you don't trust the Silverlight client. If you are worried that someone will break into the Silverlight runtime and somehow put bad data into your object's fields (perhaps bypassing your business logic, etc), then extra precautions are required. To address that concern, the server-side data portal can optionally invoke an "observer" or "factory" (I'm still debating the name of this thing).

To do this, on your server-side business object code (in the server-only partial class) you use the MobileFactory attribute to specify the type name of the factory object, and the method names to be called for create, fetch, update and delete operations (the only operations the data portal supports).

[MobileFactory("MyProject.MyFactory, MyProject", "Create", "Fetch", "Update", "Delete")]
public partial class MockEditableRoot

Then you must implement the factory class:

public class MyFactory
{
  public object Create(object criteria)
  {
    // create, initialize and return new object here
  }

  public object Fetch(object criteria)
  {
    // create, load and return object here 
  }

  public object Update(object inbound)
  {
    // insert, update or delete object here
    // return resulting object
  }

  public void Delete(object criteria)
  {
    // delete object here 
  }
}

The criteria or business object from the client does materialize on the server. Of course on the server it materializes within code you control, and so you can safely interact with the object from within the methods of this factory. Here, you can force re-running of the validation rules, apply extra authorization rules or other processing you see fit - all on the app server. Only if you are happy with the object would you then invoke the "real" data portal to actually allow the persistence to occur.

Tuesday, June 24, 2008 10:24:09 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  | 

 Monday, June 23, 2008

A couple people have suggested that I might be abandoning VB. Not so!

My first love was Pascal - VAX Pascal actually, which was more like Modula II in many ways. What an awesome language!

My next love was VAX Basic. Now that VB has structured exception handling in .NET, it has finally caught up to where VAX Basic was in the early 90's. No kidding.

Of course after VAX Basic came VB.

And after VB came .NET. I love .NET. I love .NET with VB and C#. C# is just VB with semi-colons, but VB is just C# without semi-colons too. I gave up on the silly language war thing a couple years ago, and am happy to let either or both language live or die by the hand of its users. The language thing was distracting me from truly enjoying .NET.

When it comes to writing books, it is really important to remember that they fund CSLA .NET. As much as I love what I do, I've got kids that will go to college in the (scarily near) future, so I can't work for free. So when I write a book, I can't ignore that C# books outsell VB books around 3:1 (it used to be 2:1, but the market has continued to shift). I still think it is worth writing a VB edition to get that 25% of the market, but you must admit that it makes a lot of sense to go for the 75% first!

It takes several weeks to port a book from one language to the other. The current plan for Expert 2008 Business Objects in C# is October (though I fear that may slip), and with the conversion time and publication schedule constraints, that pushes the VB edition into early 2009. Apress just hasn't put the VB book on their public release list yet, but that doesn't mean I don't plan to do that edition.

When it comes to CSLA Light, I'm doing it in C# because of the 3:1 split, and so again am focusing on C# first.

Whether I do a VB version of the framework or not depends on whether I decide to write a book on the creation and design of CSLA Light. I may or may not. If I don't write a book on the design of the actual framework, I won't port (and then maintain) the framework into a second language.

It is a ridiculous amount of work to maintain CSLA .NET twice, and I really don't like the idea of maintaining CSLA Light twice too. You have no idea how much writing, testing and debugging everything twice slows down progress (and eliminates fun). As wonderful as Instant C# and Instant VB are, the dual effort is a continually increasing barrier to progress.

I might write an ebook on using CSLA Light, in which case I'd leave the framework in C#, but create reference apps in both VB and C# so I can do both editions of the ebook. I think this is the most likely scenario. Certainly VB-compatibility has shaped a couple CSLA Light design decisions already - I won't allow a design that precludes the use of VB to build a CSLA Light app.

(The lack of multi-line lambdas and/or anonymous delegates in VB is a real barrier though... Worse even, than the poor way C# handles implementation of interfaces...)

In the end though, like all of us, I need to be where the market is vibrant. Where I can make money from my hard work. Just now, there's more money to be had from C# content and so that takes priority. But there are a lot of people using VB, and (assuming the sales ratio doesn't slip further) in my view it is worth producing content in the VB space as well.

Monday, June 23, 2008 9:18:31 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [8]  | 

 Saturday, June 14, 2008

We're nearly done with the final serialization implementation. At this point it is possible to clone objects on Silverlight and on .NET using the same MobileFormatter. By extension, this means that objects can be cloned from Silverlight to .NET and visa versa, though we don't have tests for that yet. (and there's a bunch of cleanup and detail work to be done for completeness - but the core engine is there and working)

The approach we've taken is automatic for managed backing fields in a subclass of BusinessBase or ReadOnlyBase. It is also automatic for BusinessListBase, ReadOnlyListBase, etc. It is not automatic for custom criteria classes, but is automatic for SingleCriteria.

The approach does allow for serialization of private backing fields, as long as you override a couple methods in your business class to get/set the field values. This is quite comparable to the PropertyBag scheme from VB6, and is conceptually similar to implementing ISerializable (though not the same due to some required features that aren't in Silverlight - there's a reason Microsoft didn't implement something like the BinaryFormatter).

What this means is that when using only managed backing fields, you have to do no work at all. Your objects will just serialize. If you are using one or more private backing fields you need to do something like this:

namespace MyApp
{
  [Serializable]
  public class CustomerEdit : BusinessBase<CustomerEdit>
  {
    protected override void OnGetState(SerializationInfo info)
    {
      base.GetState(info);
      info.AddValue("MyApp.CustomerEdit._id", _id);
      info.AddValue("MyApp.CustomerEdit._name", _name);
    }

    protected override void OnSetState(SerializationInfo info)
    {
      base.SetState(info);
      _id = info.GetValue<int>("MyApp.CustomerEdit._id";
      _name = info.GetValue<string>("MyApp.CustomerEdit._name");
    }
  }
}

Assuming, of course, that you have two private backing fields, _id and _name. The one important restriction is that the types of all fields must be primitive types, or types that can be coerced using Csla.Utilities.CoerceValue() (which means the value can be converted to/from a string as required by the DataContractSerializer).

Of course if you have a field value that can't be automatically converted to/from a string, you can do the conversion yourself in the OnGetState/OnSetState methods.

This will get a little more complex when we implement UndoableBase (which is the next item on the list), because your overrides must differentiate between "NonSerialized" and "NotUndoable" fields - by hand of course. I expect the final result will look more like this:

namespace MyApp
{
  [Serializable]
  public class CustomerEdit : BusinessBase<CustomerEdit>
  {
    protected override void OnGetState(SerializationInfo info, StateModes mode)
    {
      base.GetState(info);
      if (mode == StateModes.Serialization)
        info.AddValue("MyApp.CustomerEdit._id", _id);
      info.AddValue("MyApp.CustomerEdit._name", _name);
    }

    protected override void OnSetState(SerializationInfo info, StateModes mode)
    {
      base.SetState(info);
      if (mode == StateModes.Serialization)
        _id = info.GetValue<int>("MyApp.CustomerEdit._id";
      _name = info.GetValue<string>("MyApp.CustomerEdit._name");
    }
  }
}

The StateModes enum will have two values: Serialization and Undo. This will allow you to exclude certain fields that are serialization-only or perhaps undo-only. I think this is an edge case for the most part, but the option will be there.

Child objects in CSLA .NET 3.5 and later should always be kept in managed backing fields, and so will be handled automatically. If you have a pressing need to store a child object reference in a private backing field, there are also OnGetChildren() and OnSetChildren() methods you can override. The code is slightly more complex, but is very prescriptive (you either do it right or it won't work :) ) - but I see this as an edge case too, and so I'm not worried if it is a little more complex.

On the whole I'm pretty pleased with this approach. It automates as many cases as can be automated without using reflection, but provides a great deal of extensibility and flexibility for those who don't want to use managed backing fields.

Saturday, June 14, 2008 8:58:12 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  | 

 Thursday, June 12, 2008

The MobileFormatter serializer being created for CSLA Light serializes objects that implement IMobileObject. CSLA Light and CSLA .NET classes will implement this interface so the business developer doesn't normally need to worry about it.

(the exception being when a business object uses private backing fields, in which case the business object developer will need to override OnGetState() and OnSetState() to get/set the private fields they've declared)

To organize the implementation, we are planning to introduce two new base classes to CSLA: MobileObject and MobileList<T>. The following diagram shows how the new inheritance hierarchy will work:

MobileObjectCD

Note that Silverlight doesn't have a BindingList<T> type, and so CSLA Light will supply that type. CSLA .NET already uses BindingList<T> extensively, and so this will provide parity on both sides of the data portal.

In other words, this will be the inheritance hierarchy for both CSLA .NET and CSLA Light.

It is also the case that FieldDataManager, the object that manages all the managed backing field values in CSLA 3.5, must serialize itself as well. And so will the BrokenRulesCollection.

FMCD

The overall hierarchy remains as it is in CSLA .NET, we're just inserting MobileObject and MobileList at the top of the hierarchy (or as high as possible in the case of .NET).

This will allow the MobileFormatter to interact with any CSLA-derived business class, automatically serializing all managed backing fields and the child objects contained in the FieldManager of a business object, or the inner list of any MobileList (BindingList<T>;).

Thursday, June 12, 2008 2:28:48 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

I've been engaged in a discussion around CSLA .NET on an MSDN architecture forum - you can see the thread here. I put quite a bit of time/effort into one of my replies, and I wanted to repost it here for broader distribution:

I don’t think it is really fair to relate CSLA .NET to CSLA Classic. I totally rewrote the framework for .NET (at least 4 times actually – trying different approaches/concepts), and the only way in which CSLA .NET relates to CSLA Classic is through some of the high level architectural goals around the use of mobile objects and the minimization of UI code.

The use of LSet in VB5/6, btw, was the closest approximation to the concept of a union struct from C or Pascal or a common block from FORTRAN possible in VB. LSet actually did a memcopy operation, and so wasn’t as good as a union struct, but was radically faster than any other serialization option available in VB at the time. So while it was far from ideal, it was the best option available back then.

Obviously .NET provides superior options for serialization through the BinaryFormatter and NetDataContractSerializer, and CSLA .NET makes use of them. To be fair though, a union struct would still be radically faster Smile

Before I go any further, it is very important to understand the distinction between ‘layers’ and ‘tiers’. Clarity of wording is important when having this kind of discussion. I discuss the difference in Chapter 1 of my Expert 2005 Business Objects book, and in several blog posts – perhaps this one is best:

http://www.lhotka.net/weblog/MiddletierHostingEnterpriseServicesIISDCOMWebServicesAndRemoting.aspx

The key thing is that a layer is a logical separation of concerns, and a tier directly implies a process or network boundary. Layers are a design constraint, tiers are a deployment artifact.

How you layer your code is up to you. Many people, including myself, often use assemblies to separate layers. But that is really just a crutch – a reminder to have discipline. Any clear separation is sufficient. But you are absolutely correct, in that a great many developers have trouble maintaining that discipline without the clear separation provided by having different code in different projects (assemblies).

1)

CSLA doesn’t group all layers into a single assembly. Your business objects belong in one layer – often one assembly – and so all your business logic (validation, calculation, data manipulation, authorization, etc) are in that assembly.

Also, because CSLA encourages the use of object-oriented design and programming, encapsulation is important. And other OO concepts like data hiding are encouraged. This means that the object must manage its own fields. Any DAL will be working with data from the object’s fields. So the trick is to get the data into and out of the private fields of the business object without breaking encapsulation. I discussed the various options around this issue in my previous post.

Ultimately the solution in most cases is for the DAL to provide and consume the data through some clearly defined interface (ADO.NET objects or DTOs) so the business object can manage its own fields, and can invoke the DAL to handle the persistence of the data.

To be very clear then, CSLA enables separation of the business logic into one assembly and the data access code into a separate assembly.

However, it doesn’t force you to do this, and many people find it simpler to put the DAL code directly into the DataPortal_XYZ methods of their business classes. That’s fine – there’s still logical separation of concerns and logical layering – it just isn’t as explicit as putting that code in a separate assembly. Some people have the discipline to make that work, and if they do have that discipline then there’s nothing wrong with the approach imo.

2)

I have no problem writing business rules in code. I realize that some applications have rules that vary so rapidly or widely that the only real solution is to use a metadata-driven rules engine, and in that case CSLA isn’t a great match.

But let’s face it, most applications don’t change that fast. Most applications consist of business logic written in C#/VB/Java/etc. CSLA simply helps formalize what most people already do, by providing a standardized approach for implementing business and validation rules such that they are invoked efficiently and automatically as needed.

Also consider that CSLA’s approach separates the concept of a business rule from the object itself. You then link properties on an object to the rules that apply to that object. This linkage can be dynamic – metadata-driven. Though the rules themselves are written as code, you can use a table-driven scheme to link rules to properties, allowing for SaaS scenarios, etc.

3)

This is an inaccurate assumption. CSLA .NET requires a strong separation between the UI and business layers, and allows for a very clear separation between the business and data access layers, and you can obviously achieve separation between the data access and data storage layers.

This means that you can easily have UI specialists that know little or nothing about OO design or other business layer concepts. In fact, when using WPF it is possible for the UI to only have UI-specific code – the separation is cleaner than is possible with Windows Forms or Web Forms thanks to the improvements in data binding.

Also, when using ASP.NET MVC (in its present form at least), the separation is extremely clear. Because the CSLA-based business objects implement all business logic, the view and controller are both very trivial to create and maintain. A controller method is typically just the couple lines of code necessary to call the object’s factory and connect it to the view, or to call the MVC helper to copy data from the postback into the object and to have the object save itself. I’m really impressed with the MVC framework when used in conjunction with CSLA .NET.

And it means that you can have data access specialists that only focus on ADO.NET, LINQ to SQL, EF, nHibernate or whatever. In my experience this is quite rare – very few developers are willing to be pigeonholed into such a singularly uninteresting aspect of software – but perhaps your experiences have been different.

Obviously it is always possible to have database experts who design and implement physical and logical database designs.

4)

I entirely agree that the DTO design pattern is incredibly valuable when building services. But no one pattern is a silver bullet and all patterns have both positive and negative consequences. It is the responsibility of professional software architects, designers and developers to use the appropriate patterns at the appropriate times to achieve the best end results.

CSLA .NET enables, but does not require, the concept of mobile objects. This concept is incredibly powerful, and is in use by a great many developers. Anyone passing disconnection ADO recordsets, or DataSets or hashtables/dictionaries/lists across the network uses a form of mobile objects. CSLA simply wraps a pre-existing feature of .NET and makes it easier for you to pass your own rich objects across the network.

Obviously only the object’s field values travel across the network. This means that a business object consumes no more network bandwidth than a DTO. But mobile objects provide a higher level of transparency in that the developer can work with essentially the same object model, and the same behaviors, on either side of the network.

Is this appropriate for all scenarios? No. Decisions about whether the pattern is appropriate for any scenario or application should be based on serious consideration of the positive and negative consequences of the pattern. Like any pattern, mobile objects has both types of consequence.

If you look at my blog over the past few years, I’ve frequently discussed the pros and cons of using a pure service-oriented approach vs an n-tier approach. Typically my n-tier arguments pre-suppose the use of mobile objects, and there are some discussions explicitly covering mobile objects.

The DTO pattern is a part of any service-oriented approach, virtually by definition. Though it is quite possible to manipulate your XML messages directly, most people find that unproductive and prefer to use a DTO as an intermediary – which makes sense for productivity even if it isn’t necessarily ideal for performance or control.

The DTO pattern can be used for n-tier approaches as well, but it is entirely optional. And when compared to other n-tier techniques involving things like the DataSet or mobile objects the DTO pattern’s weaknesses become much more noticeable.

The mobile object pattern is not useful for any true service-oriented scenario (note that I’m not talking about web services here, but rather true message-based SOA). This is because your business objects are your internal implementation and should never be directly exposed as part of your external contract. That sort of coupling between your external interface contract and your internal implementation is always bad – and is obviously inappropriate when using DTOs as well. DTOs can comprise part of your external contract, but should never be part of your internal implementation.

The mobile object pattern is very useful for n-tier scenarios because it enables some very powerful application models. Most notably, the way it is done in CSLA, it allows the application to switch between a 1-, 2- and 3-tier physical deployment merely by changing a configuration file. The UI, business and data developers do not need to change any code or worry about the details – assuming they’ve followed the rules for building proper CSLA-based business objects.

Thursday, June 12, 2008 8:58:29 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  | 

Dunn Training is working with some people in Ireland to put together a CSLA .NET training class. If you are in Ireland, the UK or perhaps Europe, you may be interested. This CSLA forum post has some more information.

Thursday, June 12, 2008 8:14:43 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Tuesday, June 10, 2008

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.

Tuesday, June 10, 2008 8:01:50 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  | 

 Thursday, April 24, 2008

Dunn Training has been offering a very good 3 day class on CSLA .NET for some time now, with lots of great feedback. And this class continues (with a sold-out class coming up in Toronto).

As a compliment to that class, Dunn is now lining up a bigger and deeper 5 day master class. The plan is to have just two of these each year.

This master class is quite different from the 3 day class. It will have more lecture, deeper labs and a faster pace. They tell me the intent is to cover everything from OO design to CSLA object creation to WPF/Windows/Web/WCF/WF interface design to LINQ in one intense week.

Not only will this be the ultimate in CSLA .NET training, it'll be some incredibly awesome training on .NET itself!!

Thursday, April 24, 2008 2:45:39 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [5]  | 

 Wednesday, April 23, 2008

I spent some time over the past few days using my prototype Silverlight serializer to build a prototype Silverlight data portal. It is still fairly far from complete, but at least I've proved out the basic concept and uncovered some interesting side-effects of living in Silverlight.

The good news is that the basic concept of the data portal works. Defining objects that physically move between the Silverlight client and a .NET web server is practical, and works in a manner similar to the pure .NET data portal.

The bad news is that it can't work exactly like the pure .NET data portal, and the technique does require some manual effort when creating the business assemblies (yes, plural).

The approach I'm taking involves having two business assemblies (VS projects) that share many of the same code files. Suppose you want to have a Person object move between the client and server. You need Person in a Silverlight class library and in a .NET class library. This means two projects are required, even if they have the same code file.

Visual Studio makes this reasonable, because you can create the file in one project (say the Silverlight class library) and then Add Existing Item and use the Link feature to get that same file included into a .NET class library project.

I also make the class be a partial class, so I can add extra code to the .NET class library implementation. The result is:

BusinessLibrary.Client (Silverlight class library)
  -> Person.cs

BusinessLibrary.Server (.NET class library)
  -> Person.cs (linked from BusinessLibrary.Client)
  -> Person.Server.cs

One key thing is that both projects build a file called BusinessLibrary.dll. Also, because Person.cs is a shared file, it obviously has the same namespace. This is all very important, because the serializer requires that the fully qualified type name ("namespace.type,assembly") be the same on client and server. In my case it is "BusinessLibrary.Person,BusinessLibrary".

The Person.Server.cs file contains the server-only parts of the Person class - it is just the rest of the partial class. The only catch here is that it can not define any fields because that would obviously confuse the serializer since those fields wouldn't exist on the client. Well, actually it could define fields as long as they were marked as NonSerialized.

Of course you could also have a partial Person.Client.cs in the Silverlight class library - though I haven't found a need for that just yet.

One thing I'm debating is whether the .NET side of the data portal should just directly delegate Silverlight calls into the "real" data portal - effectively acting as a passive router between Silverlight and the .NET objects. OR the .NET side of the data portal could invoke specific methods (like Silverlight_Create(), Silverlight_Update(), etc) so the business developer can include code to decide whether the calls should be processed on the server at all.

The first approach is simple, and certainly makes for a compelling story because it works very much like CSLA today. The Silverlight client gets/updates objects in a very direct manner.

The second approach is a little more complex, but might be better because I'm not sure you should blindly trust anything coming from the Silverlight client. You can make a good argument that Silverlight is always outside the trust boundary of your server application, so blindly passing calls from the client through the data portal may not be advisable.

Either way, what's really cool is that the original .NET data portal remains fully intact. This means that the following two physical deployment scenarios are available:

Silverlight -> Web server -> database
Silverlight -> Web server -> App server -> database

Whether the web/app server is in 2- or 3-tier configuration is just a matter of how the original .NET data portal (running on the web server) is configured. I think that's awesome, as it easily enables two very common web server configurations.

The big difference in how the Silverlight data portal works as compared to the .NET data portal is on the client. In Silverlight you should never block the main UI thread, which means calls to the server should be asynchronous. Which means the UI code can't just do this:

var person = Person.GetPerson(123);

That sort of synchronous call would block the UI thread and lock the browser. Instead, my current approach requires the UI developer to write code like this:

var dp = new Csla.DataPortal();
dp.FetchCompleted +=
  new EventHandler<Csla.DataPortalResult<Person>>(dp_FetchCompleted);
dp.BeginFetch<Person>(new SingleCriteria<int>(123));

with a dp_FetchCompleted() method like:

private void dp_FetchCompleted(object sender, Csla.DataPortalResult<Person> e)
{
  if (e.Error != null)
    // e.Error is an exception - deal with the issue
  else
    // e.Object is your result - use it
}

So the UI code is more cumbersome than in .NET, but it follows the basic service-calling technique used in any current Silverlight code, and I don't think it is too bad. It isn't clear how to make this any simpler really.

Wednesday, April 23, 2008 8:08:36 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [13]  | 

 Sunday, April 13, 2008

Silverlight 2.0 doesn't have an equivalent to the BinaryFormatter or NetDataContractSerializer. This makes some things quite challenging - in my case building CSLA Light. CSLA .NET requires high-fidelity serialization both for implementation of the Clone() operation and within the data portal.

I've been working on building a Silverlight-compatible equivalent to the BinaryFormatter/NDCS. It turns out to be quite hard due to the limitations of the Silverlight sandbox.

For example, Silverlight does have reflection, even against private fields. However, you can only get or set a private field with code inside the same class as the field declaration. You can't get/set a field from another object, or even from a base class or subclass. The reflection call must be in the same class!

At this point I have a prototype serializer that works in some limited scenarios. It is a starting point. Some aspects aren't ideal, but may just be the way they are to get around how Silverlight works. Still, the end result is relatively cool.

To use the serializer:

  1. Build the Csla project (it is a Silverlight Class Library) and reference it from your Silverlight application
  2. In your business class, add a using/Imports statement for Csla.Serialization
  3. Add the Serializable attribute to your class
  4. You class must also either inherit from MobileObject or implement the IMobileObject interface (I recommend using inheritance, as otherwise you'll have to write a lot of nasty code)
  5. You must override GetValue() and SetValue() in your class - these methods are called by the MobileFormatter so you can reflect against your private fields. See the example below to see how this works
  6. You can now use the MobileFormatter much like you would the BinaryFormatter. See the example below

The MobileFormatter is far from complete. But it can serialize/deserialize fields of an object that contain primitive types (anything that works with Convert.ChangeType()). And it handles references to other serializable objects, both single objects and lists of serializable objects (if they implement IMobileObject or inherit from MobileList<T> ).

I'm pretty sure it can't handle arrays, nor can it handle any list type other than (effectively) List<T>. I'm not sure what it will do with enums or other types - just haven't gotten that far yet.

Here's a serializable object:

using System;
using Csla.Serialization;

namespace SilverlightApplication1
{
  [Serializable]
  public class Person : MobileObject
  {
    #region Serialization

    protected override object GetValue(System.Reflection.FieldInfo field)
    {
      if (field.DeclaringType == typeof(Person))
        return field.GetValue(this);
      else
        return base.GetValue(field);
    }

    protected override void SetValue(System.Reflection.FieldInfo field, object value)
    {
      if (field.DeclaringType == typeof(Person))
        field.SetValue(this, value);
      else
        base.SetValue(field, value);
    }

    #endregion

    public string Name { get; set; }

    [NonSerialized]
    private DateTime _birthdate;
    public DateTime BirthDate
    {
      get { return _birthDate; }
      set { _birthdate = value; }
    } 
  }
}

And here's how to serialize/deserialize the object:

var p = new Person();

var formatter = new Csla.Serialization.MobileFormatter();
var buffer = new System.IO.MemoryStream();
formatter.Serialize(buffer, p);

buffer.Position = 0;
var copyOfP = (Person)formatter.Deserialize(buffer);

Though it is unfortunate that every business class must implement GetValue() and SetValue(), I think that is a relatively small price to pay to get nearly the same capability as we have in .NET with the BinaryFormatter in terms of cloning objects, and more importantly in terms of serializing them across the network with full fidelity.

Sunday, April 13, 2008 7:42:40 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [6]  | 

 Saturday, April 12, 2008

Someone on the CSLA .NET discussion forum recently asked what new .NET 3.5 features I used in CSLA .NET 3.5. The poster noted that there are a lot of new features in .NET 3.5, which is true. They also included some .NET 3.0 features as "new", though really those features have now been around for 15 months or so and were addressed in CSLA .NET 3.0. CSLA .NET 3.0 already added support for WCF, WPF and WF, so those technologies had very little impact on CSLA .NET 3.5.

My philosophy is to use new technologies only if they provide value to me and my work. In the case of CSLA .NET this is extended slightly, such that I try to make sure CSLA .NET also supports new technologies that might be of value to people who use CSLA .NET.

While .NET 3.5 has a number of new technologies at various levels (UI, data, languages), many of them required no changes to CSLA to support. I like to think this is because I'm always trying to look into the future as I work on CSLA, anticipating at least some of what is coming so I can make the transition smoother. For example, this is why CSLA .NET 2.0 introduced a provider model for the data portal - because I knew WCF was coming in a couple years and I wanted to be ready.

Since CSLA .NET already supported data binding to WPF, Windows Forms and Web Forms, there was no real work to do at the UI level for .NET 3.5. I actually removed Csla.Wpf.Validator because WPF now directly supplies that behavior, but I really didn't add anything for UI support because it is already there.

Looking forward beyond 3.5, it is possible I'll need to add support for ASP.NET MVC because that technology eschews data binding in favor of other techniques to create the view - but it is too early to know for sure what I'll do in that regard.

Since CSLA .NET has always abstracted the business object concept from the data access technique you choose, it automatically supported LINQ to SQL (and will automatically support ADO.NET EF too). No changes required to do that were required, though I did add Csla.Data.ContextManager to simplify the use of L2S data context objects (as a companion to the new Csla.Data.ConnectionManager for raw ADO.NET connections). And I enhanced Csla.Data.DataMapper to have some more powerful mapping options that may be useful in some L2S or EF scenarios.

LINQ to Objects did require some work. Technically this too was optional, but I felt it was critical, and so there is now "LINQ to CSLA" functionality provided in 3.5 (thanks to my colleague Aaron Erickson). The primary feature of this is creating a synchronized view of a BusinessListBase list when you do a non-projection query, which means you can data bind the results of a non-projection query and allow the user to add/remove items from the query result and those changes are also reflected in the original list. As a cool option, LINQ to CSLA also implements indexed queries against lists, so if you are doing many queries against the same list object you should look into this as a performance booster!

So all that's left are some of the language enhancements that exist to support LINQ. And I do use some of them - mostly type inference (which I love). But I didn't go through the entire body of existing code to use the new language features. The risk of breaking functionality that has worked for 6-7 years is way too high! I can't see where anyone would choose to take such a risk with a body of code, but especially one like CSLA that is used by thousands of people world-wide.

That means I used some of the new language features in new code, and in code I had to rework anyway. And to be honest, I use those features sparingly and where I thought they helped.

I think trying to force new technologies/concepts/patterns into code is a bad idea. If a given pattern or technology obviously saves code/time/money or has other clear benefits then I use it, but I try never to get attached to some idea such that I force it into places where it doesn't fit with my overall goals.

Saturday, April 12, 2008 3:11:52 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  | 

 Thursday, April 03, 2008

CSLA .NET version 3.5 for .NET 3.5 and Visual Studio 2008 is now available for download from www.lhotka.net/cslanet/download.aspx. This version of CSLA .NET includes support for LINQ and provides substantial code reduction (often around 40%) when coding your business objects.

Check out the official launch announcement on DotNetRocks!

If you are using .NET 2.0 or 3.0 with Visual Studio 2005 or 2008 then you'll want to use CSLA .NET version 3.0.4. Version 3.0.4 includes some data binding bug fixes over version 3.0.3, and it works with .NET 2.0 or .NET 3.0. It is also available from the download page.

As always, questions and comments are welcome on the forum at http://forums.lhotka.net.

Thursday, April 03, 2008 8:27:11 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  | 

 Monday, March 24, 2008

Dunn Training is holding a three day CSLA .NET training class in Toronto, May 5-7. Dunn's three day class is a great way to jumpstart your use of CSLA .NET, and Toronto is a fun city, so this is a great opportunity!

For details go to http://www.dunntraining.com/training/schedule.htm.
Monday, March 24, 2008 8:50:29 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Monday, March 10, 2008

In a previous post I talked about the new property declaration syntax options in CSLA .NET 3.5. When it comes to child objects, if the shortest form is used then CSLA will pretty much completely take care of all parent-child object interaction so you don't have to do it by hand. This is a tremendous code savings!

So declaring a child property like this:

private static PropertyInfo<ChildList> ChildListProperty =
  RegisterProperty<ChildList>(new PropertyInfo<ChildList>("ChildList");
public ChildList ChildList
{
  get { return GetProperty<ChildList>(ChildListProperty); }
}

allows CSLA to manage the child object. Of course you do need to create the child object somewhere, such as in the DataPortal_XYZ methods:

[RunLocal]
private void DataPortal_Create()
{
  // initialize other fields here
  LoadProperty<ChildList>(ChildListProperty, ChildList.NewList());
  base.DataPortal_Create();
}

private void DataPortal_Fetch(...)
{
  // initialize other fields here
  LoadProperty<ChildList>(ChildListProperty, ChildList.GetList(this.Id));
}

Another option is to use a lazy loading scheme. There are a couple options in how you can use lazy loading. You can avoid the DataPortal_Create() implementation by just creating a new, empty list - and I do this almost all the time now:

private static PropertyInfo<ChildList> ChildListProperty =
  RegisterProperty<ChildList>(new PropertyInfo<ChildList>("ChildList");
public ChildList ChildList
{
  get
  {
    if (!FieldManager.FieldExists(ChildListProperty))
      SetProperty<ChildList>(ChildListProperty, ChildList.NewList());
    return GetProperty<ChildList>(ChildListProperty);
  }
}

With this approach you still need to load the child data in the DataPortal_Fetch() method. The only thing this does is eliminate the need for the code in DataPortal_Create() - which often means you don't need DataPortal_Create() at all.

Another option is to truly lazy load the object by calling a factory method that actually loads the object with existing data:

private static PropertyInfo<ChildList> ChildListProperty =
  RegisterProperty<ChildList>(new PropertyInfo<ChildList>("ChildList");
public ChildList ChildList
{
  get
  {
    if (!FieldManager.FieldExists(ChildListProperty))
      SetProperty<ChildList>(ChildListProperty, ChildList.GetList(this.Id));
    return GetProperty<ChildList>(ChildListProperty);
  }
}

Obviously this requires that the ChildList class implement a GetList() factory that calls the data portal so it can be loaded independently from its parent. This is different from the first example, where GetList() would use the new child data portal support (or could be implemented the old 3.0 way). I'll discuss the new child data portal support in a future blog post.

If you use lazy loading, CSLA will automatically ensure that the newly created child has its edit level set correctly and that all data binding events cascade appropriately.

in all cases you no longer need to write code in a parent object like this:

protected override bool IsDirty
{
  get
  {
    return base.IsDirty || _childList.IsDirty;
  }
}

protected override bool IsValid
{
  get
  {
    return base.IsValid && _childList.IsValid;
  }
}

Nor do you need to do any hooking of child object events like PropertyChanged or ListChanged - that's all automatic as well.

Monday, March 10, 2008 10:15:41 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  | 

 Sunday, March 09, 2008