OK I'm using the Csla Data Mapper in an ASP.Net webforms UI (I dream of doing MVC one day) and have a boolean property firing which sets a default date on another property - the user can also set the date in the UI.
When mapping, if the date control maps first it gets set to e.g. 18th Nov, but then the boolean setproperty fires and resets my date to today (e.g. 17th Nov).
Is there anyway to have the business layer object indicate the order I want the data mapper to fire the property mapping in, or will I nedd to / be better off removing the DataMapper and do it manually mapping the properties in my desired order.
But of course, even if I do it manually the UI developer would need to know the business property dependancies. Not such a problem as they have the source code, but what if they didn't have the source code?
Thanks,
Richard.
It has been a long time since I looked at DataMapper, but I think you can control the order by creating your own DataMap.
By default DataMapper uses reflection to find the properties, and it loops through them. It might be the case that if you provide a DataMap it walks through the elements in the DataMap in order. It might not work that way - I honestly don't remember - you can look at the code to see.
Otherwise you'll probably need to do manual mapping.
Though another alternative is to suppress rules during the mapping process. This is a feature of CSLA 4, and can be useful when batch loading properties in scenarios like a web site. The feature is discussed in the Using CSLA 4: Creating Business Objects ebook.
I think manual mapping is what I'll need to do in my scenario - thanks for the quick response.
ALthough I may look at extending the DataMapper - I wonder if I can add custom attributes to the properties, and then have the DataMapper fetch the properties in order and map that way.
E.g.
<AttributeUsage(AttributeTargets.Property, _ AllowMultiple:=False, Inherited:=False)> _ Public Class BindingOrderAttribute Inherits System.Attribute Private m_BindingOrder As Integer Public Sub New(ByVal bindingOrder As Integer) m_BindingOrder = bindingOrder End Sub Public Property BindingOrder() As Integer Get Return m_BindingOrder End Get Set(ByVal Value As Integer) m_BindingOrder = Value End Set End Property End Class
Then do this on my properties....
Private Shared ReadOnly _isSignOffSMProperty As PropertyInfo(Of Boolean) = RegisterProperty(Of Boolean)(Function(p As BusinessCase) p.IsSignOffSM) <BindingOrder(0)> _ Public Property IsSignOffSM() As Boolean Get Return GetProperty(_isSignOffSMProperty) End Get Set(ByVal value As Boolean) SetProperty(_isSignOffSMProperty, value) If value = True Then Me.SignOffSMDate = New SmartDate(Date.Now).ToString SetProperty(_SMUserIDProperty, Csla.ApplicationContext.User.Identity.Name) Else Me.SignOffSMDate = New SmartDate(True).ToString SetProperty(_SMUserIDProperty, "") End If End Set End Property
Private Shared ReadOnly _SignOffSMDateProperty As PropertyInfo(Of SmartDate) = RegisterProperty(Of SmartDate)(Function(p As BusinessCase) p.SignOffSMDate, New SmartDate(True)) <BindingOrder(1)> _ Public Property SignOffSMDate() As String Get Return GetPropertyConvert(Of SmartDate, String)(_SignOffSMDateProperty) End Get Set(ByVal value As String) SetPropertyConvert(Of SmartDate, String)(_SignOffSMDateProperty, value) End Set End Property
and then have another MapInBindingOrder method
public static void Map( System.Collections.IDictionary source, object target, bool suppressExceptions, params string[] ignoreList) {
//TODO: Can we modify this to reflect and get properties on object in our custom attribute order ascending,
//and then map the values across???????
List<string> ignore = new List<string>(ignoreList); foreach (string propertyName in source.Keys) { if (!ignore.Contains(propertyName)) { try { SetPropertyValue(target, propertyName, source[propertyName]); } catch (Exception ex) { if (!suppressExceptions) throw new ArgumentException( String.Format("{0} ({1})", Resources.PropertyCopyFailed, propertyName), ex); } } } }
Is this approach sound? Technically doable?
I think I like it better as the business object is indicating the best way to map.
Thoughts?
Copyright (c) Marimer LLC