11using System.Collections.Generic;
15using System.Reflection;
26 [System.Diagnostics.DebuggerStepThrough]
31 private string _businessObjectType;
35 private List<IPropertyInfo> _propertyList;
45 SetPropertyList(businessObjectType);
46 _fieldData =
new IFieldData[_propertyList.Count];
53 internal void SetPropertyList(Type businessObjectType)
55 _businessObjectType = businessObjectType.AssemblyQualifiedName;
56 _propertyList = GetConsolidatedList(businessObjectType);
75 return new List<IPropertyInfo>(_propertyList);
100 get {
return _propertyList.Count > 0; }
103 #region ConsolidatedPropertyList
105 private static Dictionary<Type, List<IPropertyInfo>> _consolidatedLists =
new Dictionary<Type, List<IPropertyInfo>>();
107 private static List<IPropertyInfo> GetConsolidatedList(Type type)
109 List<IPropertyInfo> result =
null;
113 found = _consolidatedLists.TryGetValue(type, out result);
119 lock (_consolidatedLists)
121 if (_consolidatedLists.ContainsKey(type))
123 result = _consolidatedLists[type];
127 result = CreateConsolidatedList(type);
128 _consolidatedLists.Add(type, result);
135 private static List<IPropertyInfo> CreateConsolidatedList(Type type)
138 List<IPropertyInfo> result =
new List<IPropertyInfo>();
142 List<Type> hierarchy =
new List<Type>();
145 hierarchy.Add(current);
146 current = current.BaseType;
147 }
while (current !=
null && !current.Equals(typeof(BusinessBase)));
150 for (
int index = hierarchy.Count - 1; index >= 0; index--)
152 var source = PropertyInfoManager.GetPropertyListCache(hierarchy[index]);
153 source.IsLocked =
true;
154 result.AddRange(source);
159 foreach (var item
in result)
161 if (item.Index == -1)
177 #region Get/Set/Find fields
186 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)]
194 return _fieldData[propertyInfo.
Index];
196 catch (IndexOutOfRangeException ex)
206 var field = _fieldData[prop.
Index];
210 _fieldData[prop.
Index] = field;
214 catch (IndexOutOfRangeException ex)
220 internal IPropertyInfo FindProperty(
object value)
223 foreach (var item
in _fieldData)
225 if (item !=
null && item.Value !=
null && item.Value.Equals(value))
226 return _propertyList[index];
241 internal void SetFieldData(IPropertyInfo prop,
object value)
245 valueType = value.GetType();
247 valueType = prop.Type;
248 value = Utilities.CoerceValue(prop.Type, valueType,
null, value);
249 var field = GetOrCreateFieldData(prop);
265 internal void SetFieldData<P>(IPropertyInfo prop, P value)
267 var field = GetOrCreateFieldData(prop);
268 if (field is IFieldData<P> fd)
284 internal IFieldData LoadFieldData(IPropertyInfo prop,
object value)
288 valueType = value.GetType();
290 valueType = prop.Type;
291 value = Utilities.CoerceValue(prop.Type, valueType,
null, value);
292 var field = GetOrCreateFieldData(prop);
311 internal IFieldData LoadFieldData<P>(IPropertyInfo prop, P value)
313 var field = GetOrCreateFieldData(prop);
314 var fd = field as IFieldData<P>;
331 internal void RemoveField(IPropertyInfo prop)
335 var field = _fieldData[prop.Index];
339 catch (IndexOutOfRangeException ex)
357 return _fieldData[propertyInfo.
Index] !=
null;
359 catch (IndexOutOfRangeException ex)
378 var field = _fieldData[propertyInfo.
Index];
380 result = field.IsDirty;
386 catch (IndexOutOfRangeException ex)
388 throw new InvalidOperationException(Properties.Resources.PropertyNotRegistered, ex);
394 #region IsValid/IsDirty/IsBusy
402 foreach (var item
in _fieldData)
403 if (item !=
null && !item.IsValid)
414 foreach (var item
in _fieldData)
415 if (item !=
null && item.IsDirty)
424 internal void MarkClean()
426 foreach (var item
in _fieldData)
427 if (item !=
null && item.IsDirty)
431 internal bool IsBusy()
433 foreach (var item
in _fieldData)
434 if (item !=
null && item.IsBusy)
441 #region IUndoableObject
443 private readonly Stack<byte[]> _stateStack =
new Stack<byte[]>();
450 get {
return _stateStack.Count; }
453 void Core.IUndoableObject.CopyState(
int parentEditLevel,
bool parentBindingEdit)
455 if (this.
EditLevel + 1 > parentEditLevel)
460 for (var index = 0; index < _fieldData.Length; index++)
462 var item = _fieldData[index];
468 child.CopyState(parentEditLevel, parentBindingEdit);
481 using (MemoryStream buffer =
new MemoryStream())
483 var formatter = SerializationFormatterFactory.GetFormatter();
484 var stateList =
new MobileList<IFieldData>(state.ToList());
485 formatter.Serialize(buffer, stateList);
486 _stateStack.Push(buffer.ToArray());
490 void Core.IUndoableObject.UndoChanges(
int parentEditLevel,
bool parentBindingEdit)
494 if (this.
EditLevel - 1 != parentEditLevel)
495 throw new UndoException(
string.Format(
Resources.
EditLevelMismatchException,
"UndoChanges"),
this.GetType().Name, _parent !=
null ? _parent.GetType().Name :
null,
this.EditLevel, parentEditLevel + 1);
497 IFieldData[] state =
null;
498 using (MemoryStream buffer =
new MemoryStream(_stateStack.Pop()))
501 var formatter = SerializationFormatterFactory.GetFormatter();
502 state = ((MobileList<IFieldData>)(formatter.Deserialize(buffer))).ToArray();
505 for (var index = 0; index < _fieldData.Length; index++)
507 var oldItem = state[index];
508 var item = _fieldData[index];
511 var undoable = item.
Value as IUndoableObject;
512 if (undoable !=
null)
516 undoable.UndoChanges(parentEditLevel, parentBindingEdit);
518 _fieldData[index] =
null;
523 _fieldData[index] = oldItem;
528 void Core.IUndoableObject.AcceptChanges(
int parentEditLevel,
bool parentBindingEdit)
530 if (this.
EditLevel - 1 != parentEditLevel)
531 throw new UndoException(
string.Format(
Resources.
EditLevelMismatchException,
"AcceptChanges"),
this.GetType().Name, _parent !=
null ? _parent.GetType().Name :
null,
this.EditLevel, parentEditLevel + 1);
538 foreach (var item
in _fieldData)
542 var child = item.Value as IUndoableObject;
546 child.AcceptChanges(parentEditLevel, parentBindingEdit);
555 #region Child Objects
568 List<object> result =
new List<object>();
569 foreach (var item
in _fieldData)
571 result.Add(item.Value);
583 foreach (var item
in _fieldData)
587 object obj = item.Value;
602 Server.ChildDataPortal portal =
new Server.ChildDataPortal();
603 foreach (var item
in _fieldData)
607 object obj = item.Value;
609 portal.UpdateAll(obj, parameters);
616 #region IMobileObject Members
630 info.
AddValue(
"_businessObjectType", _businessObjectType);
632 if (mode ==
StateMode.Serialization && _stateStack.Count > 0)
633 info.
AddValue(
"_stateStack", _stateStack.ToArray());
640 info.AddValue(
"child_" + data.
Name,
true,
false);
642 info.AddValue(data.
Name, SerializationFormatterFactory.GetFormatter().Serialize(data.
Value), data.
IsDirty);
647 base.OnGetState(info, mode);
668 base.OnGetChildren(info, formatter);
683 string type = (string)info.
Values[
"_businessObjectType"].Value;
685 SetPropertyList(businessObjecType);
690 if (info.
Values.ContainsKey(
"_stateStack"))
692 var stackArray = info.GetValue<
byte[][]>(
"_stateStack");
693 foreach (var item
in stackArray.Reverse())
694 _stateStack.Push(item);
697 _fieldData =
new IFieldData[_propertyList.Count];
702 if (info.Values.ContainsKey(property.
Name))
706 IFieldData data = GetOrCreateFieldData(property);
707 if (value.Value !=
null &&
709 typeof(
IMobileObject).IsAssignableFrom(Nullable.GetUnderlyingType(property.
Type) ?? property.
Type) &&
712 data.
Value = SerializationFormatterFactory.GetFormatter().Deserialize((
byte[])value.Value);
714 else data.
Value = value.Value;
724 if (!info.Values.ContainsKey(
"child_" + property.
Name) || !info.GetValue<
bool>(
"child_" + property.
Name))
725 _fieldData[
property.Index] =
null;
729 data.
Value =
property.DefaultValue;
733 base.OnSetState(info, mode);
745 if (info.Children.ContainsKey(property.
Name))
749 IFieldData data = GetOrCreateFieldData(property);
750 data.
Value = formatter.GetObject(childData.ReferenceId);
751 if (!childData.IsDirty)
755 base.OnSetChildren(info, formatter);
767 const BindingFlags attr =
768 BindingFlags.Static |
769 BindingFlags.Public |
770 BindingFlags.DeclaredOnly |
771 BindingFlags.NonPublic;
777 var fields = t.GetFields(attr);
778 if (fields.Length > 0)
779 fields[0].GetValue(
null);
This is the base class from which most business objects will be derived.
This is the non-generic base class from which most business objects will be derived.
Contains a field value and related metadata.
Manages properties and property data for a business object.
override void OnGetState(SerializationInfo info, StateMode mode)
Override this method to insert your field values into the MobileFormatter serialzation stream.
bool HasFields
Gets a value indicating whether there are any managed fields available.
bool IsFieldDirty(IPropertyInfo propertyInfo)
Gets a value indicating whether the specified field has been changed.
int EditLevel
Gets the current edit level of the object.
override void OnSetState(SerializationInfo info, StateMode mode)
Override this method to retrieve your field values from the MobileFormatter serialzation stream.
List< IPropertyInfo > GetRegisteredProperties()
Returns a copy of the property list for the business object.
FieldDataManager()
Creates an instance of the object.
bool IsDirty()
Returns a value indicating whether any fields are dirty.
override void OnSetChildren(SerializationInfo info, MobileFormatter formatter)
Deserializes child objects.
IFieldData GetFieldData(IPropertyInfo propertyInfo)
Gets the IFieldData object for a specific field.
void UpdateChildren(params object[] parameters)
Invokes the data portal to update all child objects contained in the list of fields.
static void ForceStaticFieldInit(Type type)
Forces initialization of the static fields declared by a type, and any of its base class types.
bool IsValid()
Returns a value indicating whether all fields are valid.
bool FieldExists(IPropertyInfo propertyInfo)
Returns a value indicating whether an IFieldData entry exists for the specified property.
void UpdateAllChildren(params object[] parameters)
Invokes the data portal to update all child objects, including those which are not dirty,...
List< object > GetChildren()
Returns a list of all child objects contained in the list of fields.
IPropertyInfo GetRegisteredProperty(string propertyName)
Returns the IPropertyInfo object corresponding to the property name.
override void OnGetChildren(SerializationInfo info, MobileFormatter formatter)
Serializes child objects.
Inherit from this base class to easily create a serializable class.
Exception indicating a problem with the use of the n-level undo feature in CSLA .NET.
This is the client-side DataPortal.
static void UpdateChild(object child)
Inserts, updates or deletes an existing child business object.
A strongly-typed resource class, for looking up localized strings, etc.
static string PropertyIsPrivateField
Looks up a localized string similar to Attempt to read/load private field property in managed propert...
static string PropertyNotRegistered
Looks up a localized string similar to One or more properties are not registered for this type.
static string EditLevelMismatchException
Looks up a localized string similar to Edit level mismatch in {0}.
static string PropertyNameNotRegisteredException
Looks up a localized string similar to Property '{0}' not registered.
Object that contains information about a single child reference.
Object that contains information about a single field.
Object containing the serialization data for a specific object.
Dictionary< string, FieldData > Values
Dictionary containg field data.
int ReferenceId
Reference number for this object.
void AddChild(string name, int referenceId)
Adds a child to the list of child references.
void AddValue(string name, object value)
Adds a value to the serialization stream.
Defines the members required by a field data storage object.
object Value
Gets or sets the field value.
void MarkClean()
Marks the field as unchanged.
string Name
Gets the name of the field.
Defines the common methods required by all editable CSLA single objects.
Defines the common methods required by all editable CSLA collection objects.
string Name
Gets the member name value.
Maintains metadata about a property.
int Index
Gets or sets the index position for the managed field storage behind the property.
RelationshipTypes RelationshipType
Gets the relationship between the declaring object and the object reference in the property.
Type Type
Gets the type of the property.
Core.FieldManager.IFieldData NewFieldData(string name)
Gets a new field data container for the property.
bool IsDirty
Returns true if this object's data, or any of its fields or child objects data, has been changed.
Defines the methods required to participate in n-level undo within the CSLA .NET framework.
Interface to be implemented by any object that supports serialization by the SerializationFormatterFa...
StateMode
Indicates the reason the MobileFormatter functionality has been invoked.
RelationshipTypes
List of valid relationship types between a parent object and another object through a managed propert...
@ Serializable
Prevents updating or inserting until the transaction is complete.