编写C#泛型方法实现字典到对象实例列表的映射
解决方案
实现思路
核心是遍历Dictionary<long, string>的键值对,将键映射到目标类T的Id属性、值映射到Value属性。以下提供几种不同灵活度的实现方式,适配不同场景需求。
方法实现
方法1:反射驱动的通用实现
无需目标类定义特定构造函数,只要T拥有可写的long类型Id和string类型Value属性即可:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; public static class DictionaryExtensions { public static IEnumerable<T> ToIdValueEnumerable<T>(this Dictionary<long, string> dictionary) where T : new() { if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); var idProp = typeof(T).GetProperty(nameof(T.Id), BindingFlags.Public | BindingFlags.Instance); var valueProp = typeof(T).GetProperty(nameof(T.Value), BindingFlags.Public | BindingFlags.Instance); if (idProp == null || !idProp.CanWrite) throw new InvalidOperationException($"{typeof(T)}必须包含可写的long类型'Id'属性"); if (valueProp == null || !valueProp.CanWrite) throw new InvalidOperationException($"{typeof(T)}必须包含可写的string类型'Value'属性"); foreach (var kvp in dictionary) { var instance = new T(); idProp.SetValue(instance, kvp.Key); valueProp.SetValue(instance, kvp.Value); yield return instance; } } }
方法2:构造函数/委托驱动的高性能实现
如果目标类可以定义特定构造函数,或者允许自定义实例创建逻辑,这种方式性能更优:
public static class DictionaryExtensions { // 重载1:依赖T的(long, string)构造函数 public static IEnumerable<T> ToIdValueEnumerable<T>(this Dictionary<long, string> dictionary) where T : class { if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); var constructor = typeof(T).GetConstructor(new[] { typeof(long), typeof(string) }); if (constructor == null) throw new InvalidOperationException($"{typeof(T)}需要包含接收(long, string)参数的构造函数"); foreach (var kvp in dictionary) { var instance = (T)constructor.Invoke(new object[] { kvp.Key, kvp.Value }); yield return instance; } } // 重载2:自定义实例创建逻辑,灵活度最高 public static IEnumerable<T> ToIdValueEnumerable<T>(this Dictionary<long, string> dictionary, Func<long, string, T> factory) { if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); if (factory == null) throw new ArgumentNullException(nameof(factory)); return dictionary.Select(kvp => factory(kvp.Key, kvp.Value)); } }
使用示例
假设有目标类:
public class MyData { public long Id { get; set; } public string Value { get; set; } // 可选:用于方法2重载1的构造函数 public MyData(long id, string value) { Id = id; Value = value; } }
调用方式:
var dict = new Dictionary<long, string> { { 1, "First" }, { 2, "Second" } }; // 方法1调用 var result1 = dict.ToIdValueEnumerable<MyData>(); // 方法2重载1调用(需对应构造函数) var result2 = dict.ToIdValueEnumerable<MyData>(); // 方法2重载2调用(自定义实例逻辑) var result3 = dict.ToIdValueEnumerable((id, val) => new MyData { Id = id, Value = val });
选择建议
- 追求通用性(无需目标类修改):选方法1;
- 追求性能且目标类可定义构造函数:选方法2重载1;
- 需要自定义映射逻辑(比如属性名不一致、额外初始化):选方法2重载2。
内容的提问来源于stack exchange,提问作者ClintCC
相关产品推荐
相关产品推荐

