CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
FieldDataManager.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="FieldDataManager.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Manages properties and property data for</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.Linq;
10using System.IO;
11using System.Collections.Generic;
12using System.Reflection;
13#if NET5_0_OR_GREATER
14using System.Runtime.Loader;
15
16using Csla.Runtime;
17#endif
18using Csla.Properties;
21using System.Threading.Tasks;
22
24{
30#if TESTING
31 [System.Diagnostics.DebuggerStepThrough]
32#endif
35 {
36 private string _businessObjectType;
37 [NonSerialized]
38 BusinessBase _parent;
39 [NonSerialized()]
40 private List<IPropertyInfo> _propertyList;
41 private IFieldData[] _fieldData;
42
43 private ApplicationContext ApplicationContext { get; set; }
45
49 public FieldDataManager() { }
50
51 internal FieldDataManager(ApplicationContext applicationContext, Type businessObjectType)
52 {
53 ApplicationContext = applicationContext;
54 SetPropertyList(businessObjectType);
55 _fieldData = new IFieldData[_propertyList.Count];
56 }
57
62 internal void SetPropertyList(Type businessObjectType)
63 {
64 _businessObjectType = businessObjectType.AssemblyQualifiedName;
65 _propertyList = GetConsolidatedList(businessObjectType);
66 }
67
71 internal void SetParent(BusinessBase parent)
72 {
73 _parent = parent;
74 }
75
82 public List<IPropertyInfo> GetRegisteredProperties()
83 {
84 return new List<IPropertyInfo>(_propertyList);
85 }
86
95 public IPropertyInfo GetRegisteredProperty(string propertyName)
96 {
97 var result = GetRegisteredProperties().Where(c => c.Name == propertyName).FirstOrDefault();
98 if (result == null)
99 throw new ArgumentOutOfRangeException(string.Format(Resources.PropertyNameNotRegisteredException, propertyName));
100 return result;
101 }
102
107 public bool HasFields
108 {
109 get { return _propertyList.Count > 0; }
110 }
111
112 #region ConsolidatedPropertyList
113
114#if NET5_0_OR_GREATER
115 private static Dictionary<Type, Tuple<string, List<IPropertyInfo>>> _consolidatedLists = new Dictionary<Type, Tuple<string, List<IPropertyInfo>>>();
116#else
117 private static readonly Dictionary<Type, List<IPropertyInfo>> _consolidatedLists = new();
118#endif
119
120 private static List<IPropertyInfo> GetConsolidatedList(Type type)
121 {
122 List<IPropertyInfo> result = null;
123
124 var found = false;
125
126 try
127 {
128#if NET5_0_OR_GREATER
129 found = _consolidatedLists.TryGetValue(type, out var consolidatedListsInfo);
130
131 result = consolidatedListsInfo?.Item2;
132#else
133 result = _consolidatedLists[type];
134#endif
135 }
136 catch
137 { /* failure will drop into !found block */ }
138
139 if (!found)
140 {
141 lock (_consolidatedLists)
142 {
143#if NET5_0_OR_GREATER
144 if (_consolidatedLists.ContainsKey(type))
145 {
146 result = _consolidatedLists[type].Item2;
147 }
148 else
149 {
150 result = CreateConsolidatedList(type);
151
152 // Cached items of consolidated lists should not be flushed if they are referenced to main application - "AssemblyLoadContext.Default".
153 // It is required for shared classes which are declared in main application but was activated first time inside active dynamic "ContextualReflectionScope".
154 // In that case, cached types are referenced to main application context and should not be flushed because
155 // "PropertyInfoManager" will not register their static CSLA properties second time - they have been registered already and cached in main application
156 // during startup.
157 var cacheInstance = AssemblyLoadContextManager.CreateCacheInstance(type, result, OnAssemblyLoadContextUnload, true);
158
159 _consolidatedLists.Add(type, cacheInstance);
160 }
161#else
162 if (_consolidatedLists.ContainsKey(type))
163 {
164 result = _consolidatedLists[type];
165 }
166 else
167 {
168 result = CreateConsolidatedList(type);
169
170 _consolidatedLists.Add(type, result);
171 }
172#endif
173 }
174 }
175
176 return result;
177 }
178
179 private static List<IPropertyInfo> CreateConsolidatedList(Type type)
180 {
182 List<IPropertyInfo> result = new List<IPropertyInfo>();
183
184 // get inheritance hierarchy
185 Type current = type;
186 List<Type> hierarchy = new List<Type>();
187 do
188 {
189 hierarchy.Add(current);
190 current = current.BaseType;
191 } while (current != null && !current.Equals(typeof(BusinessBase)));
192
193 // walk from top to bottom to build consolidated list
194 for (int index = hierarchy.Count - 1; index >= 0; index--)
195 {
196 var source = PropertyInfoManager.GetPropertyListCache(hierarchy[index]);
197 source.IsLocked = true;
198 result.AddRange(source);
199 }
200
201 // set Index properties on all unindexed PropertyInfo objects
202 int max = -1;
203 foreach (var item in result)
204 {
205 if (item.Index == -1)
206 {
207 max++;
208 item.Index = max;
209 }
210 else
211 {
212 max = item.Index;
213 }
214 }
215 // return consolidated list
216 return result;
217 }
218
219#endregion
220
221#region Get/Set/Find fields
222
230 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)]
232 {
233 if ((propertyInfo.RelationshipType & RelationshipTypes.PrivateField) == RelationshipTypes.PrivateField)
234 throw new InvalidOperationException(Resources.PropertyIsPrivateField);
235
236 try
237 {
238 return _fieldData[propertyInfo.Index];
239 }
240 catch (IndexOutOfRangeException ex)
241 {
242 throw new InvalidOperationException(Resources.PropertyNotRegistered, ex);
243 }
244 }
245
246 private IFieldData GetOrCreateFieldData(IPropertyInfo prop)
247 {
248 try
249 {
250 var field = _fieldData[prop.Index];
251 if (field == null)
252 {
253 field = prop.NewFieldData(prop.Name);
254 _fieldData[prop.Index] = field;
255 }
256 return field;
257 }
258 catch (IndexOutOfRangeException ex)
259 {
260 throw new InvalidOperationException(Resources.PropertyNotRegistered, ex);
261 }
262 }
263
264 internal IPropertyInfo FindProperty(object value)
265 {
266 var index = 0;
267 foreach (var item in _fieldData)
268 {
269 if (item != null && item.Value != null && item.Value.Equals(value))
270 return _propertyList[index];
271 index += 1;
272 }
273 return null;
274 }
275
285 internal void SetFieldData(IPropertyInfo prop, object value)
286 {
287 Type valueType;
288 if (value != null)
289 valueType = value.GetType();
290 else
291 valueType = prop.Type;
292 value = Utilities.CoerceValue(prop.Type, valueType, null, value);
293 var field = GetOrCreateFieldData(prop);
294 field.Value = value;
295 }
296
309 internal void SetFieldData<P>(IPropertyInfo prop, P value)
310 {
311 var field = GetOrCreateFieldData(prop);
312 if (field is IFieldData<P> fd)
313 fd.Value = value;
314 else
315 field.Value = value;
316 }
317
328 internal IFieldData LoadFieldData(IPropertyInfo prop, object value)
329 {
330 Type valueType;
331 if (value != null)
332 valueType = value.GetType();
333 else
334 valueType = prop.Type;
335 value = Utilities.CoerceValue(prop.Type, valueType, null, value);
336 var field = GetOrCreateFieldData(prop);
337 field.Value = value;
338 field.MarkClean();
339 return field;
340 }
341
355 internal IFieldData LoadFieldData<P>(IPropertyInfo prop, P value)
356 {
357 var field = GetOrCreateFieldData(prop);
358 if (field is IFieldData<P> fd)
359 fd.Value = value;
360 else
361 field.Value = value;
362 field.MarkClean();
363 return field;
364 }
365
374 internal void RemoveField(IPropertyInfo prop)
375 {
376 try
377 {
378 var field = _fieldData[prop.Index];
379 if (field != null)
380 field.Value = null;
381 }
382 catch (IndexOutOfRangeException ex)
383 {
384 throw new InvalidOperationException(Resources.PropertyNotRegistered, ex);
385 }
386 }
387
396 public bool FieldExists(IPropertyInfo propertyInfo)
397 {
398 try
399 {
400 return _fieldData[propertyInfo.Index] != null;
401 }
402 catch (IndexOutOfRangeException ex)
403 {
404 throw new InvalidOperationException(Resources.PropertyNotRegistered, ex);
405 }
406 }
407
416 public bool IsFieldDirty(IPropertyInfo propertyInfo)
417 {
418 try
419 {
420 bool result = false;
421 var field = _fieldData[propertyInfo.Index];
422 if (field != null)
423 result = field.IsDirty;
424 else
425 result = false;
426 return result;
427
428 }
429 catch (IndexOutOfRangeException ex)
430 {
431 throw new InvalidOperationException(Properties.Resources.PropertyNotRegistered, ex);
432 }
433 }
434
435#endregion
436
437#region IsValid/IsDirty/IsBusy
438
443 public bool IsValid()
444 {
445 foreach (var item in _fieldData)
446 if (item != null && !item.IsValid)
447 return false;
448 return true;
449 }
450
455 public bool IsDirty()
456 {
457 foreach (var item in _fieldData)
458 if (item != null && item.IsDirty)
459 return true;
460 return false;
461 }
462
467 internal void MarkClean()
468 {
469 foreach (var item in _fieldData)
470 if (item != null && item.IsDirty)
471 item.MarkClean();
472 }
473
474 internal bool IsBusy()
475 {
476 foreach (var item in _fieldData)
477 if (item != null && item.IsBusy)
478 return true;
479 return false;
480 }
481
482#endregion
483
484#region IUndoableObject
485
486 private readonly Stack<byte[]> _stateStack = new();
487
491 public int EditLevel
492 {
493 get { return _stateStack.Count; }
494 }
495
496 void Core.IUndoableObject.CopyState(int parentEditLevel, bool parentBindingEdit)
497 {
498 if (this.EditLevel + 1 > parentEditLevel)
499 throw new UndoException(
500 string.Format(
501 Resources.EditLevelMismatchException, "CopyState"), this.GetType().Name,
502 _parent?.GetType().Name, this.EditLevel, parentEditLevel - 1);
503
504 IFieldData[] state = new IFieldData[_propertyList.Count];
505
506 for (var index = 0; index < _fieldData.Length; index++)
507 {
508 var item = _fieldData[index];
509 if (item != null)
510 {
511 if (item.Value is IUndoableObject child)
512 {
513 // cascade call to child
514 child.CopyState(parentEditLevel, parentBindingEdit);
515 // indicate that there was a value here
516 state[index] = new FieldData<bool>(item.Name);
517 }
518 else
519 {
520 // add the IFieldData object
521 state[index] = item;
522 }
523 }
524 }
525
526 // serialize the state and stack it
527 using MemoryStream buffer = new MemoryStream();
528 var formatter = SerializationFormatterFactory.GetFormatter(ApplicationContext);
529 var stateList = new MobileList<IFieldData>(state.ToList());
530 formatter.Serialize(buffer, stateList);
531 _stateStack.Push(buffer.ToArray());
532 }
533
534 void Core.IUndoableObject.UndoChanges(int parentEditLevel, bool parentBindingEdit)
535 {
536 if (EditLevel > 0)
537 {
538 if (this.EditLevel - 1 != parentEditLevel)
539 throw new UndoException(
540 string.Format(Resources.EditLevelMismatchException, "UndoChanges"),
541 this.GetType().Name, _parent?.GetType().Name, this.EditLevel, parentEditLevel + 1);
542
543 IFieldData[] state = null;
544 using (MemoryStream buffer = new MemoryStream(_stateStack.Pop()))
545 {
546 buffer.Position = 0;
547 var formatter = SerializationFormatterFactory.GetFormatter(ApplicationContext);
548 state = ((MobileList<IFieldData>)(formatter.Deserialize(buffer))).ToArray();
549 }
550
551 for (var index = 0; index < _fieldData.Length; index++)
552 {
553 var oldItem = state[index];
554 var item = _fieldData[index];
555 if (item != null)
556 {
557 if (item.Value is IUndoableObject undoable)
558 {
559 // current value is undoable
560 var doUndo = (oldItem != null);
561 if (!doUndo)
562 {
563 var propInfo = _propertyList.Where(r => r.Index == index).First();
564 doUndo = propInfo.RelationshipType.HasFlag(RelationshipTypes.LazyLoad);
565 }
566 if (doUndo)
567 undoable.UndoChanges(parentEditLevel, parentBindingEdit);
568 else
569 _fieldData[index] = null;
570 continue;
571 }
572 }
573 // restore IFieldData object into field collection
574 _fieldData[index] = oldItem;
575 }
576 }
577 }
578
579 void Core.IUndoableObject.AcceptChanges(int parentEditLevel, bool parentBindingEdit)
580 {
581 if (this.EditLevel - 1 != parentEditLevel)
582 throw new UndoException(
583 string.Format(Resources.EditLevelMismatchException, "AcceptChanges"),
584 this.GetType().Name, _parent?.GetType().Name, this.EditLevel, parentEditLevel + 1);
585
586 if (EditLevel > 0)
587 {
588 // discard latest recorded state
589 _stateStack.Pop();
590
591 foreach (var item in _fieldData)
592 {
593 if (item != null)
594 {
595 if (item.Value is IUndoableObject child)
596 {
597 // cascade call to child
598 child.AcceptChanges(parentEditLevel, parentBindingEdit);
599 }
600 }
601 }
602 }
603 }
604
605#endregion
606
607#region Child Objects
608
618 public List<object> GetChildren()
619 {
620 List<object> result = new List<object>();
621 foreach (var item in _fieldData)
622 if (item != null && (item.Value is IEditableBusinessObject || item.Value is IEditableCollection))
623 result.Add(item.Value);
624 return result;
625 }
626
633 public void UpdateChildren(params object[] parameters)
634 {
636 foreach (var item in _fieldData)
637 {
638 if (item != null)
639 {
640 object obj = item.Value;
641 if (obj is IEditableBusinessObject || obj is IEditableCollection)
642 dp.UpdateChild(obj, parameters);
643 }
644 }
645 }
646
653 public void UpdateAllChildren(params object[] parameters)
654 {
655 Server.ChildDataPortal portal = new Server.ChildDataPortal(ApplicationContext);
656 foreach (var item in _fieldData)
657 {
658 if (item != null)
659 {
660 object obj = item.Value;
661 if (obj is IEditableBusinessObject || obj is IEditableCollection)
662 portal.UpdateAll(obj, parameters);
663 }
664 }
665 }
666
672 public async Task UpdateChildrenAsync(params object[] parameters)
673 {
674 Server.ChildDataPortal portal = new Server.ChildDataPortal(ApplicationContext);
675 foreach (var item in _fieldData)
676 {
677 if (item != null)
678 {
679 object obj = item.Value;
680 if (obj is IEditableBusinessObject || obj is IEditableCollection)
681 await portal.UpdateAsync(obj, parameters).ConfigureAwait(false);
682 }
683 }
684 }
685
692 public async Task UpdateAllChildrenAsync(params object[] parameters)
693 {
694 Server.ChildDataPortal portal = new Server.ChildDataPortal(ApplicationContext);
695 foreach (var item in _fieldData)
696 {
697 if (item != null)
698 {
699 object obj = item.Value;
700 if (obj is IEditableBusinessObject || obj is IEditableCollection)
701 await portal.UpdateAllAsync(obj, parameters).ConfigureAwait(false);
702 }
703 }
704 }
705
706 #endregion
707
708 #region IMobileObject Members
709
720 protected override void OnGetState(SerializationInfo info, StateMode mode)
721 {
722 info.AddValue("_businessObjectType", _businessObjectType);
723
724 if (mode == StateMode.Serialization && _stateStack.Count > 0)
725 info.AddValue("_stateStack", _stateStack.ToArray());
726
727 foreach (IFieldData data in _fieldData)
728 {
729 if (data != null)
730 {
731 if (data.Value is IUndoableObject)
732 info.AddValue("child_" + data.Name, true, false);
733 else if (mode == StateMode.Undo && data.Value is IMobileObject)
734 info.AddValue(data.Name, SerializationFormatterFactory.GetFormatter(ApplicationContext).Serialize(data.Value), data.IsDirty);
735 else if(data.Value is not IMobileObject)
736 info.AddValue(data.Name, data.Value, data.IsDirty);
737 }
738 }
739 base.OnGetState(info, mode);
740 }
741
747 protected override void OnGetChildren(SerializationInfo info, MobileFormatter formatter)
748 {
749 foreach (IFieldData data in _fieldData)
750 {
751 if (data != null)
752 {
753 if (data.Value is IMobileObject mobile)
754 {
755 SerializationInfo childInfo = formatter.SerializeObject(mobile);
756 info.AddChild(data.Name, childInfo.ReferenceId, data.IsDirty);
757 }
758 }
759 }
760 base.OnGetChildren(info, formatter);
761 }
762
773 protected override void OnSetState(SerializationInfo info, StateMode mode)
774 {
775 string type = (string)info.Values["_businessObjectType"].Value;
776 Type businessObjecType = Csla.Reflection.MethodCaller.GetType(type);
777 SetPropertyList(businessObjecType);
778
779 if (mode == StateMode.Serialization)
780 {
781 _stateStack.Clear();
782 if (info.Values.ContainsKey("_stateStack"))
783 {
784 var stackArray = info.GetValue<byte[][]>("_stateStack");
785 foreach (var item in stackArray.Reverse())
786 _stateStack.Push(item);
787 }
788
789 _fieldData = new IFieldData[_propertyList.Count];
790 }
791
792 foreach (IPropertyInfo property in _propertyList)
793 {
794 if (info.Values.ContainsKey(property.Name))
795 {
796 SerializationInfo.FieldData value = info.Values[property.Name];
797
798 IFieldData data = GetOrCreateFieldData(property);
799 if (value.Value != null &&
800 mode == StateMode.Undo &&
801 typeof(IMobileObject).IsAssignableFrom(Nullable.GetUnderlyingType(property.Type) ?? property.Type) &&
802 !typeof(IUndoableObject).IsAssignableFrom(Nullable.GetUnderlyingType(property.Type) ?? property.Type))
803 {
804 data.Value = SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize((byte[])value.Value);
805 }
806 else data.Value = value.Value;
807
808 if (!value.IsDirty)
809 data.MarkClean();
810 }
811 else if (mode == StateMode.Undo && !((property.RelationshipType & RelationshipTypes.PrivateField) == RelationshipTypes.PrivateField))
812 {
813 IFieldData data = GetFieldData(property);
814 if (data != null)
815 {
816 if (!info.Values.ContainsKey("child_" + property.Name) || !info.GetValue<bool>("child_" + property.Name))
817 _fieldData[property.Index] = null;
818
819 // We don't want to reset children during an undo.
820 else if (!typeof(IMobileObject).IsAssignableFrom(data.Value.GetType()))
821 data.Value = property.DefaultValue;
822 }
823 }
824 }
825 base.OnSetState(info, mode);
826 }
827
833 protected override void OnSetChildren(SerializationInfo info, MobileFormatter formatter)
834 {
835 foreach (IPropertyInfo property in _propertyList)
836 {
837 if (info.Children.ContainsKey(property.Name))
838 {
839 SerializationInfo.ChildData childData = info.Children[property.Name];
840
841 IFieldData data = GetOrCreateFieldData(property);
842 data.Value = formatter.GetObject(childData.ReferenceId);
843 if (!childData.IsDirty)
844 data.MarkClean();
845 }
846 }
847 base.OnSetChildren(info, formatter);
848 }
849
850#endregion
851
857 public static void ForceStaticFieldInit(Type type)
858 {
859 const BindingFlags attr =
860 BindingFlags.Static |
861 BindingFlags.Public |
862 BindingFlags.DeclaredOnly |
863 BindingFlags.NonPublic;
864 lock (type)
865 {
866 var t = type;
867 while (t != null)
868 {
869 var fields = t.GetFields(attr);
870 if (fields.Length > 0)
871 fields[0].GetValue(null);
872 t = t.BaseType;
873 }
874 }
875 }
876#if NET5_0_OR_GREATER
877
878 private static void OnAssemblyLoadContextUnload(AssemblyLoadContext context)
879 {
880 lock (_consolidatedLists)
881 AssemblyLoadContextManager.RemoveFromCache(_consolidatedLists, context);
882 }
883#endif
884 }
885}
Provides consistent context information between the client and server DataPortal objects.
object CreateInstanceDI(Type objectType, params object[] parameters)
Creates an object using 'Activator.CreateInstance' using service provider (if one is available) to po...
This is the base class from which most business objects will be derived.
Definition: BusinessBase.cs:38
This is the non-generic base class from which most business objects will be derived.
Contains a field value and related metadata.
Definition: FieldData.cs:21
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 type.
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.
async Task UpdateAllChildrenAsync(params object[] parameters)
Asynchronously invokes the data portal to update all child objects, including those which are not dir...
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.
async Task UpdateChildrenAsync(params object[] parameters)
Asynchronously invokes the data portal to update all child objects contained in the list of fields.
override void OnGetChildren(SerializationInfo info, MobileFormatter formatter)
Serializes child objects.
Inherit from this base class to easily create a serializable class.
Definition: MobileObject.cs:20
Exception indicating a problem with the use of the n-level undo feature in CSLA .NET.
Client side data portal used for making asynchronous data portal calls in .NET.
Definition: DataPortalT.cs:24
void UpdateChild(T child)
Inserts, updates or deletes an existing child business object.
Definition: DataPortalT.cs:734
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.
Serializes and deserializes objects at the field level.
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.
Definition: IFieldDataT.cs:15
object Value
Gets or sets the field value.
Definition: IFieldData.cs:27
void MarkClean()
Marks the field as unchanged.
string Name
Gets the name of the field.
Definition: IFieldData.cs:21
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.
Definition: IMemberInfo.cs:23
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.
Definition: ITrackStatus.cs:73
Defines the methods required to participate in n-level undo within the CSLA .NET framework.
Implement if a class requires access to the CSLA ApplicationContext type.
ApplicationContext ApplicationContext
Gets or sets the current ApplicationContext object.
Interface to be implemented by any object that supports serialization by the SerializationFormatterFa...
StateMode
Indicates the reason the MobileFormatter functionality has been invoked.
Definition: StateMode.cs:20
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.