/// <summary> /// Generates state transfer expressions to copy a complex type. /// </summary> /// <param name="complexType"> /// Complex type that will be cloned. /// </param> /// <param name="source"> /// Variable expression for the original instance. /// </param> /// <param name="target"> /// Variable expression for the cloned instance. /// </param> /// <param name="expression"> /// Receives the generated transfer expressions. /// </param> private void GenerateFieldBasedComplexTypeTransferExpressions(Type complexType, Expression source, Expression target, ICollection <Expression> expression) { // Enumerate all of the type's fields and generate transfer expressions for each ISet <FieldInfo> skipCloneFieldInfos; IEnumerable <FieldInfo> fieldInfos = GetFieldInfosIncludingBaseClasses(complexType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, out skipCloneFieldInfos); // For those field which skip deep copying, do shallow copying by assigning the field value from the source to the target foreach (FieldInfo fieldInfo in skipCloneFieldInfos) { expression.Add(CloneExpressionHelper.CreateCopyFieldExpression(source, target, fieldInfo)); } foreach (FieldInfo fieldInfo in fieldInfos) { Type fieldType = fieldInfo.FieldType; if (IsTypePrimitiveOrString(fieldType)) { expression.Add(CloneExpressionHelper.CreateCopyFieldExpression(source, target, fieldInfo)); } else if (fieldType.IsValueType) { // A nested value type is part of the parent and will have its fields directly assigned without boxing, new instance creation or anything like that. this.GenerateFieldBasedComplexTypeTransferExpressions(fieldType, Expression.Field(source, fieldInfo), Expression.Field(target, fieldInfo), expression); } else { this.GenerateFieldBasedReferenceTypeTransferExpressions(source, target, expression, fieldInfo); } } }
/// <summary> /// Generates state transfer expressions to copy a complex type /// </summary> /// <param name="complexType">Complex type that will be cloned</param> /// <param name="source">Variable expression for the original instance</param> /// <param name="target">Variable expression for the cloned instance</param> /// <param name="expression">Receives the generated transfer expressions</param> private void GenerateFieldBasedComplexTypeTransferExpressions(Type complexType, Expression source, Expression target, ICollection <Expression> expression) { // Enumerate all of the type's fields and generate transfer expressions for each ISet <FieldInfo> skipCloneFieldInfos; var fieldInfos = GetFieldInfosIncludingBaseClasses( complexType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, out skipCloneFieldInfos); // For those field which skip deep copying, do shallow copying by assigning the field value from the source to the target foreach (var fieldInfo in skipCloneFieldInfos) { expression.Add(CloneExpressionHelper.CreateCopyFieldExpression(source, target, fieldInfo)); } foreach (var fieldInfo in fieldInfos) { var fieldType = fieldInfo.FieldType; if (fieldType.Equals(typeof(DataTable))) { expression.Add(CloneExpressionHelper.CreateCopyFieldExpression(source, target, fieldInfo)); } else if (IsTypePrimitiveOrString(fieldType)) { expression.Add(CloneExpressionHelper.CreateCopyFieldExpression(source, target, fieldInfo)); } else if (fieldType.IsValueType) { GenerateFieldBasedComplexTypeTransferExpressions(fieldType, Expression.Field(source, fieldInfo), Expression.Field(target, fieldInfo), expression); } else { GenerateFieldBasedReferenceTypeTransferExpressions(source, target, expression, fieldInfo); } } }