コード例 #1
0
ファイル: TypeExtensions.cs プロジェクト: redbaty/Proxier
        /// <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);
                    }
                }
            }
        }