You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复泛型Copy方法以实现ItemsDto到ItemsModel的对象复制?

泛型对象复制方法修复

问题背景

需要实现泛型对象复制(非克隆),将ItemsDto模型复制到ItemsModel模型中。现有泛型Copy方法仅能处理类型完全一致的属性(如int Id、List<string> Infos),但无法处理嵌套对象(如ItemDto→ItemModel)和对象列表(如List<ItemDto>→List<ItemModel>)的复制。

现有模型代码

ItemsDto

public class ItemsDto
{
  public int Id { get; set; }
  public List<ItemDto> Items { get; set; } = [];
  public ItemDto Item { get; set; } = new ItemDto();
  public List<string> Infos { get; set; } = [];
}

ItemDto

public class ItemDto
{
  public int Id { get; set; }
  public string Item { get; set; } = string.Empty;
}

ItemsModel

public partial class ItemsModel: BaseViewModel
{
  [ObservableProperty] private int _id;
  [ObservableProperty] private List<ItemModel> _items = [];
  [ObservableProperty] private ItemModel _item = new ItemModel();
  [ObservableProperty] private List<string> _infos = [];
}

ItemModel

public partial class ItemModel: BaseModel
{
  [ObservableProperty] private int _id;
  [ObservableProperty] private string _item = string.Empty;
}

修复后的泛型Copy方法

public static TTarget? Copy<TTarget, TSource>(TSource? source)
{
    if (source == null) return default;
    
    // 创建目标实例
    var target = (TTarget?)Activator.CreateInstance(typeof(TTarget));
    if (target == null) return default;

    foreach (var targetProperty in target.GetType().GetProperties())
    {
        var sourceProperty = source.GetType().GetProperty(targetProperty.Name);
        if (sourceProperty == null) continue; // 找不到对应属性则跳过,而非直接返回

        var sourceValue = sourceProperty.GetValue(source);
        if (sourceValue == null) continue;

        // 1. 类型完全一致的属性直接赋值
        if (sourceProperty.PropertyType == targetProperty.PropertyType)
        {
            targetProperty.SetValue(target, sourceValue);
            continue;
        }

        // 2. 处理嵌套对象(如ItemDto → ItemModel)
        var targetPropType = targetProperty.PropertyType;
        var sourcePropType = sourceProperty.PropertyType;
        if (!typeof(IEnumerable).IsAssignableFrom(targetPropType) && 
            targetPropType.IsClass && sourcePropType.IsClass)
        {
            // 递归调用Copy方法复制嵌套对象
            var nestedCopy = typeof(YourClassName) // 替换为包含此方法的类名
                .GetMethod(nameof(Copy))?
                .MakeGenericMethod(targetPropType, sourcePropType)
                .Invoke(null, new[] { sourceValue });
            
            targetProperty.SetValue(target, nestedCopy);
            continue;
        }

        // 3. 处理泛型列表(如List<ItemDto> → List<ItemModel>)
        if (targetPropType.IsGenericType && targetPropType.GetGenericTypeDefinition() == typeof(List<>) &&
            sourcePropType.IsGenericType && sourcePropType.GetGenericTypeDefinition() == typeof(List<>))
        {
            var sourceItemType = sourcePropType.GetGenericArguments()[0];
            var targetItemType = targetPropType.GetGenericArguments()[0];
            
            // 创建目标列表实例
            var targetList = (IList)Activator.CreateInstance(targetPropType)!;
            
            foreach (var item in (IEnumerable)sourceValue)
            {
                // 递归复制每个列表项
                var copiedItem = typeof(YourClassName) // 替换为包含此方法的类名
                    .GetMethod(nameof(Copy))?
                    .MakeGenericMethod(targetItemType, sourceItemType)
                    .Invoke(null, new[] { item });
                
                if (copiedItem != null)
                {
                    targetList.Add(copiedItem);
                }
            }
            
            targetProperty.SetValue(target, targetList);
            continue;
        }
    }

    return target;
}

关键修复点说明

  • 跳过无对应属性的情况:原代码中找不到源属性时直接返回target,改为跳过当前属性继续处理其他属性,避免中途终止复制。
  • 嵌套对象递归复制:通过反射调用自身泛型方法,实现不同类型嵌套对象的复制(如ItemDto到ItemModel),无需硬编码类型映射。
  • 泛型列表处理:识别List<T>类型,创建对应目标列表实例,逐个复制列表项并添加到目标列表中,解决原代码中错误赋值的问题。
  • 逻辑顺序优化:调整判断顺序,避免类型判断冲突,确保每种场景的处理逻辑互不干扰。

内容的提问来源于stack exchange,提问作者JBD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:35:23