如何修复泛型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
相关产品推荐
相关产品推荐

