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.
GraphMerger.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="GrapherMerger.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Defines members required for smart</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.Collections;
10using System.Collections.Generic;
11using System.Linq;
12
13namespace Csla.Core
14{
19 public class GraphMerger : Csla.Server.ObjectFactory
20 {
25 public GraphMerger(ApplicationContext applicationContext)
26 : base(applicationContext) { }
27
34 {
35 if (target is IManageProperties imp)
36 {
37 FieldManager.FieldDataManager targetFieldManager = null;
38 if (target is IUseFieldManager iufm)
39 targetFieldManager = iufm.FieldManager;
40 FieldManager.FieldDataManager sourceFieldManager = null;
41 if (source is IUseFieldManager iufms)
42 sourceFieldManager = iufms.FieldManager;
43
44 var targetProperties = imp.GetManagedProperties();
45 foreach (var item in targetProperties)
46 {
47 var sourceFieldExists = true;
48 if (sourceFieldManager != null && (item.RelationshipType & RelationshipTypes.LazyLoad) == RelationshipTypes.LazyLoad)
49 sourceFieldExists = sourceFieldManager.FieldExists(item);
50 object sourceValue = null;
51 if (sourceFieldExists)
52 sourceValue = ReadProperty(source, item);
53 if (sourceValue is IEditableBusinessObject sourceChild)
54 {
55 var targetFieldExists = true;
56 if (targetFieldManager != null && (item.RelationshipType & RelationshipTypes.LazyLoad) == RelationshipTypes.LazyLoad)
57 targetFieldExists = targetFieldManager.FieldExists(item);
58 if (targetFieldExists && ReadProperty(target, item) is IEditableBusinessObject targetChild)
59 {
60 MergeGraph(targetChild, sourceChild);
61 }
62 else
63 {
64 if ((item.RelationshipType & RelationshipTypes.PrivateField) == RelationshipTypes.PrivateField)
65 Csla.Reflection.MethodCaller.CallPropertySetter(target, item.Name, sourceChild);
66 else
67 LoadProperty(target, item, sourceChild);
68 }
69 }
70 else
71 {
72 if (sourceValue is IEditableCollection sourceList)
73 {
74 var targetFieldExists = true;
75 if (targetFieldManager != null && (item.RelationshipType & RelationshipTypes.LazyLoad) == RelationshipTypes.LazyLoad)
76 targetFieldExists = targetFieldManager.FieldExists(item);
77 if (targetFieldExists && ReadProperty(target, item) is IEditableCollection targetList)
78 {
79 MergeGraph(targetList, sourceList);
80 }
81 else
82 {
83 if ((item.RelationshipType & RelationshipTypes.PrivateField) == RelationshipTypes.PrivateField)
84 Csla.Reflection.MethodCaller.CallPropertySetter(target, item.Name, sourceList);
85 else
86 LoadProperty(target, item, sourceList);
87 }
88 }
89 else
90 {
91 if ((item.RelationshipType & RelationshipTypes.PrivateField) == RelationshipTypes.PrivateField)
92 Csla.Reflection.MethodCaller.CallPropertySetter(target, item.Name, sourceValue);
93 else
94 LoadProperty(target, item, sourceValue);
95 }
96 }
97 }
98 if (source.IsNew)
99 {
100 MarkNew(target);
101 }
102 else if (!source.IsDirty)
103 {
104 MarkOld(target);
105 }
106 else
107 {
108 CopyField(source, target, "_isDirty");
109 CopyField(source, target, "_isNew");
110 CopyField(source, target, "_isDeleted");
111 }
112 CheckRules(target);
113 }
114 }
115
116 private static void CopyField(object source, object target, string fieldName)
117 {
118 if (source == null) return;
119 if (target == null) return;
120 var sourceField = source.GetType().GetField(fieldName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
121 if (sourceField != null)
122 {
123 var targetField = target.GetType().GetField(fieldName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
124 if (targetField != null)
125 {
126 targetField.SetValue(target, sourceField.GetValue(source));
127 }
128 }
129 }
130
136 private void MergeGraph(IEditableCollection target, IEditableCollection source)
137 {
138#if !NETFX_CORE
139 var listType = target.GetType();
140 var childType = Utilities.GetChildItemType(listType);
141 var genericTypeParams = new Type[] { listType, childType };
142 var parameterTypes = new Type[] { listType, listType };
143 System.Reflection.MethodInfo methodReference;
144 if (typeof(IExtendedBindingList).IsAssignableFrom(listType))
145 methodReference = this.GetType().GetMethod("MergeBusinessBindingListGraph");
146 else
147 methodReference = this.GetType().GetMethod("MergeBusinessListGraph");
148 var gr = methodReference.MakeGenericMethod(genericTypeParams);
149 gr.Invoke(this, new object[] { target, source });
150#endif
151 }
152
158 public void MergeBusinessListGraph<T, C>(T target, T source)
159 where T : BusinessListBase<T, C>
160 where C : Core.IEditableBusinessObject
161 {
162 var deleted = new List<C>();
163 foreach (var item in target)
164 {
165 var sourceItem = source.Where(_ => _.Identity == item.Identity).FirstOrDefault();
166 if (sourceItem != null)
167 MergeGraph(item, sourceItem);
168 else
169 deleted.Add(item);
170 }
171
172 // add items not in target
173 foreach (var item in source)
174 if (target.Count(_ => _.Identity == item.Identity) == 0)
175 target.Add(item);
176
177 // remove items not in source
178 foreach (var item in deleted)
179 target.Remove(item);
180 GetDeletedList<C>(target).Clear();
181 }
182
188 public void MergeBusinessBindingListGraph<T, C>(T target, T source)
190 where C : Core.IEditableBusinessObject
191 {
192 var deleted = new List<C>();
193 foreach (var item in target)
194 {
195 var sourceItem = source.Where(_ => _.Identity == item.Identity).FirstOrDefault();
196 if (sourceItem != null)
197 MergeGraph(item, sourceItem);
198 else
199 deleted.Add(item);
200 }
201
202 // add items not in target
203 foreach (var item in source)
204 if (target.Count(_ => _.Identity == item.Identity) == 0)
205 target.Add(item);
206
207 // remove items not in source
208 foreach (var item in deleted)
209 target.Remove(item);
210 GetDeletedList<C>(target).Clear();
211 }
212 }
213}
Provides consistent context information between the client and server DataPortal objects.
This is the base class from which most business collections or lists will be derived.
This is the base class from which most business collections or lists will be derived.
Implements behavior to merge one object graph into a clone of itself (typically post-serialization).
Definition: GraphMerger.cs:20
GraphMerger(ApplicationContext applicationContext)
Creates an instance of the type.
Definition: GraphMerger.cs:25
void MergeGraph(IEditableBusinessObject target, IEditableBusinessObject source)
Merges state from source graph into target graph.
Definition: GraphMerger.cs:33
void MergeBusinessListGraph< T, C >(T target, T source)
Merges state from source graph into target graph.
Definition: GraphMerger.cs:158
void MergeBusinessBindingListGraph< T, C >(T target, T source)
Merges state from source graph into target graph.
Definition: GraphMerger.cs:188
void MarkOld(object obj)
Calls the MarkOld method on the specified object, if possible.
void MarkNew(object obj)
Calls the MarkNew method on the specified object, if possible.
void LoadProperty(object obj, IPropertyInfo propertyInfo, object newValue)
Loads a property's managed field with the supplied value.
Csla.Core.MobileList< C > GetDeletedList< C >(object obj)
Gets the list of deleted items from an editable collection.
void CheckRules(object obj)
Calls the ValidationRules.CheckRules() method on the specified object, if possible.
object ReadProperty(object obj, IPropertyInfo propertyInfo)
Reads a property's managed field value.
Defines the common methods required by all editable CSLA single objects.
Defines the common methods required by all editable CSLA collection objects.
bool IsNew
Returns true if this is a new object, false if it is a pre-existing object.
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
RelationshipTypes
List of valid relationship types between a parent object and another object through a managed propert...