Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Tuesday, July 15, 2008

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
 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
 Friday, July 11, 2008

You can watch the first of (at least two) dotnetrocks TV shows about CSLA .NET 3.5:

http://www.dnrtv.com/default.aspx?showNum=116

In this show I got about half way through discussing the major changes from version 3.0 to 3.5, so Carl and I will need to record another show to finish the discussion.

Friday, July 11, 2008 9:16:28 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Tuesday, July 1, 2008

VS Live is coming to New York in September and Las Vegas in October. I'll be speaking at both events, including a pre-con workshop covering architecture and design considerations for .NET 2.0 through 3.5 - kind of a survival guide to the many versions of .NET :)

Of course I use CSLA .NET and CSLA Light to illustrate some of the techniques you can use to minimize your risk and lower your costs as you migrate from Windows Forms to WPF or Silverlight, and from Web Forms to ASP.NET MVC or Silverlight. At the same time, I spend a lot of time talking about most of the various technologies available - my use of CSLA is incidental rather than central to the talk.

1105 Media (the people who run VS Live) put together this promo video for the show - I'm in the middle of it for a bit.

VS Live is a great show - I hope to see some of you in one of these cities!

Tuesday, July 1, 2008 2:19:06 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Wednesday, June 25, 2008

It is a good time to be a developer/software geek in the Twin Cities!

I'll be speaking at the Developer's Guild on August 12, giving a preview of CSLA Light (CSLA .NET for Silverlight) - probably its first public showing.

Wednesday, June 25, 2008 9:03:29 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 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
 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
 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
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
April, 2019 (2)
January, 2019 (1)
December, 2018 (1)
November, 2018 (1)
October, 2018 (1)
September, 2018 (3)
August, 2018 (3)
June, 2018 (4)
May, 2018 (1)
April, 2018 (3)
March, 2018 (4)
December, 2017 (1)
November, 2017 (2)
October, 2017 (1)
September, 2017 (3)
August, 2017 (1)
July, 2017 (1)
June, 2017 (1)
May, 2017 (1)
April, 2017 (2)
March, 2017 (1)
February, 2017 (2)
January, 2017 (2)
December, 2016 (5)
November, 2016 (2)
August, 2016 (4)
July, 2016 (2)
June, 2016 (4)
May, 2016 (3)
April, 2016 (4)
March, 2016 (1)
February, 2016 (7)
January, 2016 (4)
December, 2015 (4)
November, 2015 (2)
October, 2015 (2)
September, 2015 (3)
August, 2015 (3)
July, 2015 (2)
June, 2015 (2)
May, 2015 (1)
February, 2015 (1)
January, 2015 (1)
October, 2014 (1)
August, 2014 (2)
July, 2014 (3)
June, 2014 (4)
May, 2014 (2)
April, 2014 (6)
March, 2014 (4)
February, 2014 (4)
January, 2014 (2)
December, 2013 (3)
October, 2013 (3)
August, 2013 (5)
July, 2013 (2)
May, 2013 (3)
April, 2013 (2)
March, 2013 (3)
February, 2013 (7)
January, 2013 (4)
December, 2012 (3)
November, 2012 (3)
October, 2012 (7)
September, 2012 (1)
August, 2012 (4)
July, 2012 (3)
June, 2012 (5)
May, 2012 (4)
April, 2012 (6)
March, 2012 (10)
February, 2012 (2)
January, 2012 (2)
December, 2011 (4)
November, 2011 (6)
October, 2011 (14)
September, 2011 (5)
August, 2011 (3)
June, 2011 (2)
May, 2011 (1)
April, 2011 (3)
March, 2011 (6)
February, 2011 (3)
January, 2011 (6)
December, 2010 (3)
November, 2010 (8)
October, 2010 (6)
September, 2010 (6)
August, 2010 (7)
July, 2010 (8)
June, 2010 (6)
May, 2010 (8)
April, 2010 (13)
March, 2010 (7)
February, 2010 (5)
January, 2010 (9)
December, 2009 (6)
November, 2009 (8)
October, 2009 (11)
September, 2009 (5)
August, 2009 (5)
July, 2009 (10)
June, 2009 (5)
May, 2009 (7)
April, 2009 (7)
March, 2009 (11)
February, 2009 (6)
January, 2009 (9)
December, 2008 (5)
November, 2008 (4)
October, 2008 (7)
September, 2008 (8)
August, 2008 (11)
July, 2008 (11)
June, 2008 (10)
May, 2008 (6)
April, 2008 (8)
March, 2008 (9)
February, 2008 (6)
January, 2008 (6)
December, 2007 (6)
November, 2007 (9)
October, 2007 (7)
September, 2007 (5)
August, 2007 (8)
July, 2007 (6)
June, 2007 (8)
May, 2007 (7)
April, 2007 (9)
March, 2007 (8)
February, 2007 (5)
January, 2007 (9)
December, 2006 (4)
November, 2006 (3)
October, 2006 (4)
September, 2006 (9)
August, 2006 (4)
July, 2006 (9)
June, 2006 (4)
May, 2006 (10)
April, 2006 (4)
March, 2006 (11)
February, 2006 (3)
January, 2006 (13)
December, 2005 (6)
November, 2005 (7)
October, 2005 (4)
September, 2005 (9)
August, 2005 (6)
July, 2005 (7)
June, 2005 (5)
May, 2005 (4)
April, 2005 (7)
March, 2005 (16)
February, 2005 (17)
January, 2005 (17)
December, 2004 (13)
November, 2004 (7)
October, 2004 (14)
September, 2004 (11)
August, 2004 (7)
July, 2004 (3)
June, 2004 (6)
May, 2004 (3)
April, 2004 (2)
March, 2004 (1)
February, 2004 (5)
Categories
About

Powered by: newtelligence dasBlog 2.0.7226.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2019, Marimer LLC

Send mail to the author(s) E-mail



Sign In