C#如何合并两个运行时确定的同泛型类型数据?
合并同类型对象集合属性的反射实现方案
之前的反射合并方案会直接覆盖目标对象的属性值,无法满足集合类型属性的合并需求(比如List<T>的AddRange效果)。以下是针对这类场景的实现方案,通过反射识别集合属性并执行合并操作:
核心合并方法
public static void Merge<T>(T target, T source) { if (target == null || source == null) return; Type type = typeof(T); foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!property.CanWrite) continue; var targetValue = property.GetValue(target); var sourceValue = property.GetValue(source); if (sourceValue == null) continue; // 判断属性是否为可添加的集合类型(实现ICollection<T>) var collectionInterface = property.PropertyType.GetInterface(typeof(ICollection<>).FullName); if (collectionInterface != null) { // 优先使用AddRange批量添加 var addRangeMethod = property.PropertyType.GetMethod( "AddRange", new[] { typeof(IEnumerable<>).MakeGenericType(collectionInterface.GetGenericArguments()[0]) } ); if (addRangeMethod != null && targetValue != null) { addRangeMethod.Invoke(targetValue, new[] { sourceValue }); } else if (targetValue != null) { // 无AddRange则逐个添加 var addMethod = property.PropertyType.GetMethod("Add", collectionInterface.GetGenericArguments()); if (addMethod != null) { foreach (var item in sourceValue as IEnumerable) { addMethod.Invoke(targetValue, new[] { item }); } } } else { // 目标集合未初始化,直接赋值源集合 property.SetValue(target, sourceValue); } } else { // 非集合属性:仅当目标值为空时覆盖,可根据需求调整逻辑 if (targetValue == null) { property.SetValue(target, sourceValue); } } } }
在请求方法中使用
public static async Task<T> Query<T>() { var response = await RequestAsync<T>(); var response2 = await RequestAsync<T>(); // 将response2的数据合并到response中 Merge(response, response2); return response; }
注意事项
- 确保目标对象的集合属性已初始化(如示例
ItemsResponse中Items默认实例化为List<Items>),若未初始化会直接赋值源集合 - 支持所有实现
ICollection<T>的集合类型(如List<T>、HashSet<T>等),无AddRange的集合会自动逐个添加元素 - 非集合属性的处理逻辑可按需调整,比如改为总是覆盖目标值,或根据业务规则合并
内容的提问来源于stack exchange,提问作者João Fernandes
相关产品推荐
相关产品推荐

