using System;
using System.Reflection;
using System.Linq;

namespace MeterVision.Util
{
    public static class ObjectHelper
    {
        /// <summary>
        /// 将源对象的字段值复制到目标对象，复制字段名相同的部分。
        /// </summary>
        /// <typeparam name="TSource">源对象类型</typeparam>
        /// <typeparam name="TDestination">目标对象类型</typeparam>
        /// <param name="source">源对象</param>
        /// <param name="destination">目标对象</param>

        public static void CopyMatchingFields<TSource, TDestination>(TSource source, TDestination destination)
        {
            if (source == null || destination == null)
                throw new ArgumentNullException("Source or destination object cannot be null.");

            // 获取源和目标的属性
            var sourceProperties = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var destinationProperties = typeof(TDestination).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            // 创建一个字典以快速查找目标属性
            var destinationPropertyMap = destinationProperties.ToDictionary(p => p.Name, p => p);

            foreach (var sourceProperty in sourceProperties)
            {
                if (destinationPropertyMap.TryGetValue(sourceProperty.Name, out var destinationProperty))
                {
                    // 检查类型是否兼容以及目标属性是否可写
                    if (destinationProperty.CanWrite &&
                        destinationProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
                    {
                        var value = sourceProperty.GetValue(source);
                        destinationProperty.SetValue(destination, value);
                    }
                }
            }

            // 获取字段
            var sourceFields = typeof(TSource).GetFields(BindingFlags.Public | BindingFlags.Instance);
            var destinationFields = typeof(TDestination).GetFields(BindingFlags.Public | BindingFlags.Instance);

            // 创建一个字典以快速查找目标字段
            var destinationFieldMap = destinationFields.ToDictionary(f => f.Name, f => f);

            foreach (var sourceField in sourceFields)
            {
                if (destinationFieldMap.TryGetValue(sourceField.Name, out var destinationField))
                {
                    // 检查类型是否兼容
                    if (destinationField.FieldType.IsAssignableFrom(sourceField.FieldType))
                    {
                        var value = sourceField.GetValue(source);
                        destinationField.SetValue(destination, value);
                    }
                }
            }
        }
    }
    /////////////////////////////////////////////////////////////
}
