/// <summary> /// Creates a delegate to clone the specified /// </summary> /// <returns>Function to clone this data record</returns> private static Func <TRecord, TRecord> CreateCloneDelegate() { // --- Create a dynamic method var cloneMethod = new DynamicMethod("CloneFactory" + s_CloneMethods.Count, typeof(TRecord), new[] { typeof(TRecord) }, true); var il = cloneMethod.GetILGenerator(); var metadata = RecordMetadataManager.GetMetadata <TRecord>(); var cloneObject = il.DeclareLocal(typeof(TRecord)); // --- Create an empty clone of TRecord and store it il.Emit(OpCodes.Newobj, typeof(TRecord).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)); il.Emit(OpCodes.Stloc, cloneObject); // --- Copy each property value foreach (var dataColumn in metadata.DataColumns) { il.Emit(OpCodes.Ldloc, cloneObject); // cloneObject il.Emit(OpCodes.Ldarg_0); // cloneObject, origObject il.Emit(OpCodes.Call, dataColumn.PropertyInfo.GetGetMethod()); // cloneObject, origObject.dataColumn.Value il.Emit(OpCodes.Call, dataColumn.PropertyInfo.GetSetMethod()); } il.Emit(OpCodes.Ldloc, cloneObject); il.Emit(OpCodes.Ret); // --- Create the delegate var cloneDelegate = cloneMethod.CreateDelegate(Expression.GetFuncType(typeof(TRecord), typeof(TRecord))); return((Func <TRecord, TRecord>)cloneDelegate); }
/// <summary> /// Touches all data fields as if those had been modified. /// </summary> public void TouchAllFields() { // --- Let's assume this record has already been loaded _isLoaded = true; var metadata = RecordMetadataManager.GetMetadata <TRecord>(); foreach (var dataColumn in metadata.DataColumns) { if (!dataColumn.IsAutoGenerated) { _modifiedColumns.Add(dataColumn.ColumnName); } } }
/// <summary> /// Merges the changed properties from another object /// </summary> /// <param name="other">Other data record object</param> public void MergeChangesFrom(TRecord other) { // --- Let's assume this record has already been loaded _isLoaded = true; var metadata = RecordMetadataManager.GetMetadata <TRecord>(); foreach (var dataColumn in metadata.DataColumns) { var propInfo = typeof(TRecord).GetProperty(dataColumn.Name); var oldVal = propInfo.GetValue(this); var newVal = propInfo.GetValue(other); if (oldVal == null && newVal != null || oldVal != null && !oldVal.Equals(newVal)) { propInfo.SetValue(this, newVal); } } }