/// <summary> /// Copies object to another object using reflection. /// </summary> /// <param name="source">The base class instance.</param> /// <param name="target">The target.</param> /// <param name="options"></param> /// <returns></returns> public static void CopyTo(this object source, object target, CopyToOptions options) { var sourceType = source.GetType(); var ignorePrivate = !options.CopyPrivates; var sourceProperties = options.PropertiesToInclude != null && options.PropertiesToInclude.Any() ? options.PropertiesToInclude : TypeRepository.GetProperty(sourceType, ignorePrivate); var targetType = target.GetType(); var targetProperties = options.PropertiesToInclude != null && options.PropertiesToInclude.Any() ? options.PropertiesToInclude.ToDictionary(i => i.Name) : TypeRepository.GetProperty(targetType, ignorePrivate).ToDictionary(i => i.Name); foreach (var propertyInfo in sourceProperties.Except(options.PropertiesToIgnore ?? Enumerable.Empty <PropertyInfo>()) ) { if (!targetProperties.ContainsKey(propertyInfo.Name)) { continue; } var copyContext = new CopyContext(propertyInfo, source, target); var rawValue = options.Resolver.Invoke(copyContext); var value = options.DeepCloneValue ? DeepCloneObject(rawValue) : rawValue; if (options.IgnoreNulls && value == null) { continue; } var targetProperty = targetProperties[propertyInfo.Name]; if (options.UseNullableBaseType) { var trueSourceType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; var trueTargetType = Nullable.GetUnderlyingType(targetProperty.PropertyType) ?? targetProperty.PropertyType; if (!targetProperty.CanWrite) { continue; } if (trueSourceType == trueTargetType) { targetProperty.SetValue(target, value); } else if (options.TryToConvert && CanConvert(value, propertyInfo, targetProperty, out var x)) { targetProperty.SetValue(target, x); } } else { if (propertyInfo.PropertyType == targetProperty.PropertyType) { targetProperty.SetValue(target, value); } else if (options.TryToConvert && CanConvert(value, propertyInfo, targetProperty, out var x)) { targetProperty.SetValue(target, x); } } } }