infuerno.github.io

Using CSLA 4 02 Creating Business Objects

137 pages

Reference

Templates: https://github.com/MarimerLLC/csla/tree/master/Support/Templates/cs/Files

Chapter 1: Key Object Concepts (page 11)

Stereotypes

Stereotypes supported by CSLA.NET:

Stereotype Description Base Class
Editable root Read/write properties; Retrieved/stored directly BusinessBase<T>
Editable child Read/write properties; Retrieved/stored via parent BusinessBase<T>
Editable root list List object containing editable child objects. List is retrieved/stored directory BusinessListBase<T,C> BusinessBindingListBase<T,C>
Editable child list List is retrieved/stored via parent BusinessListBase<T,C> BusinessBindingListBase<T,C>
Dynamic root list Editable root objects; Retrieved/stored directly DynamicListBase<C> DynamicBindingListBase<C>
Command Executes a command on the server, reports back results CommandBase<T>
Unit of work Combines operations against several objects ReadOnlyBase<T> CommandBase<T>
Read-only root Read properties; Retrieved/stored directly ReadOnlyBase<T>
Read-only child Read properties; Retrieved/stored via parent ReadOnlyBase<T>
Read-only root list List object containing read-only child objects. List is retrieved/stored directory ReadOnlyListBase<T,C> ReadOnlyBindingListBase<T,C>
Read-only child list List is retrieved/stored via parent ReadOnlyListBase<T,C> ReadOnlyBindingListBase<T,C>
Name/value list Read name / value objects NameValueListBase<K,V>

Serializers

Object Relationships

Relationships are important because the conceptual differences mean the code which is written to implement them is also different.

Relationship Description Example
Containment Parent child relationship an OrderEdit object contains a LineItems collection, which in turn contains LineItemEdit objects. This set of objects is an object graph. The object at the top of the graph is the root object.
Using Separate and independent objects which collaborate LineItemEdit uses a TaxCalculator to calculate tax depending on country.

Equality

Object equality can mean different things - actually the same object, or two different objects containing the same values. The Equals method can be overriden, or the IEquatable interface implemented.

Basic CSLA 4 Property Concepts

Properties can become complex. A getter requires checking authorization, a setter requires checking: authorization, is new value different to existing value, PropertyChanging event, run rules, mark object as changed, PropertyChanged event.

CSLA defines a standard way to declare properties and backing fields involving:

Metadata

A static PropertyInfo field contains metadata about the property and is “registered” with the framework using the RegisterProperty method:

public static readonly PropertyInfo<string> MyTextProperty = RegisterProperty<string>(c => c.MyText);

Declaring metadata in this way is a requirement for using CSLA features.

RegisterProperty method

The RegisterProperty method registers the property’s metadata with the “field manager”, the CSLA.NET property management subsystem (with various overloads). It creates an instance of IPropertyInfo containing property metadata - which is returned to the class and can be stored in a static field. It also registers the instance with a static data structure maintained by the framework.

PropertyInfo<T> and IPropertyInfo

The RegisterProperty method either accepts a pre-created IPropertyInfo (usually a PropertyInfo<T>) or will create an instance for you. (PropertyInfo is strongly typed and therefore more efficient.)

The PropertyInfo<T> stores the property metadata (hence can be static at the class level). Elements in IPropertyInfo include: Name, Type, FriendlyName, DefaultValue (only use in value or immutable types since will be shared across all instances). The types can be extended to store extra metadata if required (advanced).

Helper Methods

Helper methods encapsulate authorisation, validation and so forth:

public string MyText
      {
get { return GetProperty(MyTextProperty); }
set { SetProperty(MyTextProperty, value); } }

with the GetProperty and SetProperty methods behaving as outlined above.

Method Description
GetProperty Gets a property, checking authorization rules
ReadProperty Gets a property, no authorization checked
SetProperty Sets a property, authorization, validation etc
LoadProperty Simply sets a property, no auth, valiadtion, events raised etc
GetPropertyConvert, ReadPropertyConvert, SetPropertyConvert, LoadPropertyConvert As above, additionally converting the new value to the correct backing field type

Backing fields

CSLA 4 allows you to implement properties using a manual backing field, or a “managed” backing field. In the latter case the CSLA .NET base class manages the property’s value on your behalf. Performance is slightly worse using managed backing fields, but generally recommended unless there is a high performance requirement.

Types of Property Declaration

Different base objects implement properties differently e.g. BusinessBase properties provide full read/write functionality; CriteriaBase properties are lightweight

Declaration type Property gets or sets
Read/write Primitive or standard .NET type
Read/write with conversion Converts to and from the type of field containing the value
Read-only Non-public setter
Read-only with conversion Non-public setter with conversion
Child Containment, typically has a non-public setter
Child with lazy loading Only loaded or created on demand
Inter-graph reference Reference to another object in the same object graph (not child)
Using reference Reference to object OUTSIDE the object graph, no setter
Manual backing fields Includes read/write and read-only
Read-Write
Read-Write with No Rules
Read-Write with Value Conversion
public static readonly PropertyInfo<TestEnum> MyStringEnumProperty = RegisterProperty<TestEnum>(c => c.MyStringEnum);
public string MyStringEnum
{
  get { return GetPropertyConvert<TestEnum, string>(MyStringEnumProperty); }
  set { SetPropertyConvert<TestEnum, string>(MyStringEnumProperty, value); }
}
Read-Only (and Read-Only with Value Conversion)
Child Object Reference
Child Object Reference with Lazy Loading

public static readonly PropertyInfo<AddressEditList> AddressesProperty = RegisterProperty<AddressEditList>(c => c.Addresses, RelationshipTypes.Child | RelationshipTypes.LazyLoad);

Properties with Manual Backing Fields

Examples of where you might use manual backing fields include:

Inter-Graph Reference

For example PersonEdit has a list of child objects of type AddressList, but also has a reference PrimaryAddress. This would be an inter-graph reference. The difference is important for how n-level undo works - need to increase edit level for all objects in the object graph ONLY ONCE.

Inter-graph references must use a manual backing field AND must have the [NotUndoable] attribute applied to that backing field. Since not a child object only the RelationshipTypes.PrivateField is needed.

public static readonly PropertyInfo<AddressEdit> PrimaryAddressProperty = RegisterProperty<AddressEdit>(c => c.PrimaryAddress, RelationshipTypes.PrivateField);
[NotUndoable]
private AddressEdit _primaryAddress = PrimaryAddressProperty.DefaultValue; public AddressEdit PrimaryAddress
{
  get { return GetProperty(PrimaryAddressProperty, _primaryAddress); }
  set { SetProperty(PrimaryAddressProperty, ref _primaryAddress, value); }
}
Using Reference

A reference to an object OUTSIDE the object graph. Best way is NOT to keep a reference to this object. Either create a reference when needed, or get a reference and store only in a local variable.

For times when a reference is REQUIRED - this MUST be implemented using a manual backing field and decorated with the [NotUndoable] and [NonSerialized] attributes. Lazy loading of this reference MUST also be implemented - since after deserialization the property value will be null.

Non-Generic LoadProperty Method

Most examples above use the generic overloaded version of the LoadProperty method e.g. LoadProperty(AddressesProperty, value).

The non-generic overload is substantially slower than the generic overload, because the value types aren’t known at compile time. Only use if there’s no way to invoke the generic overload.

Method Declarations

Similarly to properties, declaration of methods include the declaration of a static metadata field as well as use of helper methods to check authorization.

public static readonly MethodInfo TestMethod = RegisterMethod(typeof(EditableProperties), "Test");
public void Test()
{
  CanExecuteMethod(TestMethod, true); // method author must remember to add this line first
  // do some work here
}

Metastate

CSLA objects maintain their own status. Following flags are available:

Property Description Stereotypes
IsNew Object’s primary key value doesn’t exist in data store Editable root and child
IsDeleted Object is marked for deletion (and on save will delete rather than update). Generally used for child objects. Editable root and child
IsChild Child object Editable root and child, Editable list
IsDirty Has been changed (object or child) Editable root and child, Editable list
IsSelfDirty Has been changed (this object only) Editable root and child
IsValid No broken rules (object or child) Editable root and child, Editable list
IsSelfValid No broken rules (this object only) Editable root and child
IsBusy Async operations in progress (object or child) Editable root and child, Editable list
IsSelfBusy Async operations in progress (this object only) Editable root and child
IsSavable IsDirty && IsValid && !IsBusy AND user is authorised Editable root and child, Editable list
Event Description Stereotypes
PropertyChanged A property has changed Editable root and child
PropertyChanging A property is changing Editable root and child
ListChanged The list or item in the list has changed (BindingList subclasses only) Editable list
CollectionChanged The collection or item in the collection has changed (ObservableCollection subclasses only) Editable list
ChildChanged An object in the graph has changed Editable root and child, Editable list
Saved The object graph has been saved Editable root, Editable root list
BusyChanged The objects busy status has changed Editable root and child, Editable list

Accessing Metastate

Note: metastate properties do NOT support data binding

Chapter 2: Solution Structure (page 57)

Chapter 3: Object Stereotypes (page 64)

Chapter 4: Business Rules (page 91)