如何创建C#泛型流畅式属性值设置器?
实现C#泛型流畅式属性值设置器方案
我来帮你搞定这个流畅式属性设置的需求!你想要的.With(opt => opt.属性名).Set(值)链式调用,核心是要正确捕获属性的设置逻辑并关联到目标对象上。之前的实现可能没处理好属性访问器的捕获或者原对象引用的持有,导致值没正确设置。下面是完整的可运行解决方案:
1. 强类型泛型设置器实现
这个版本完全类型安全,避免装箱拆箱,性能更优:
// 泛型属性设置器类,持有目标对象和强类型属性设置委托 public class FluentPropertySetter<T, TProp> { private readonly T _targetObject; private readonly Action<T, TProp> _propertySetter; // 私有构造,通过Create方法初始化 private FluentPropertySetter(T target, Action<T, TProp> setter) { _targetObject = target; _propertySetter = setter; } // 静态创建方法,解析属性选择表达式并生成设置委托 public static FluentPropertySetter<T, TProp> Create(T target, Expression<Func<T, TProp>> propertySelector) { // 验证表达式是否为属性选择 var memberExpr = propertySelector.Body as MemberExpression; if (memberExpr == null || !(memberExpr.Member is PropertyInfo propInfo)) { throw new ArgumentException("请传入合法的属性选择表达式", nameof(propertySelector)); } // 生成强类型的属性设置委托 var setMethod = propInfo.GetSetMethod(); if (setMethod == null) { throw new InvalidOperationException($"属性{propInfo.Name}没有公开的Set方法"); } var setter = (Action<T, TProp>)Delegate.CreateDelegate(typeof(Action<T, TProp>), setMethod); return new FluentPropertySetter<T, TProp>(target, setter); } // 设置属性值,返回原对象以支持链式调用 public T Set(TProp value) { _propertySetter(_targetObject, value); return _targetObject; } } // 扩展方法,让任意对象都能调用With方法 public static class FluentSetterExtensions { public static FluentPropertySetter<T, TProp> With<T, TProp>(this T target, Expression<Func<T, TProp>> propertySelector) { return FluentPropertySetter<T, TProp>.Create(target, propertySelector); } }
2. 测试示例
用你的ClonableExampleClass来验证:
public class ClonableExampleClass { public string Name { get; set; } public int Age { get; set; } public bool IsActive { get; set; } } // 调用示例 var example = new ClonableExampleClass(); // 链式调用设置属性 example .With(opt => opt.Name).Set("Vinicius") .With(opt => opt.Age).Set(30) .With(opt => opt.IsActive).Set(true); // 验证结果 Console.WriteLine($"Name: {example.Name}, Age: {example.Age}, IsActive: {example.IsActive}"); // 输出:Name: Vinicius, Age: 30, IsActive: True
3. 实现原理说明
- 属性表达式解析:通过
Expression<Func<T, TProp>>捕获用户选择的属性,解析出对应的PropertyInfo,再生成强类型的设置委托,避免了反射调用的性能损耗。 - 目标对象持有:设置器类始终持有原对象的引用,
Set方法直接修改原对象的属性值,不会出现修改副本导致的无效设置问题。 - 链式调用支持:
Set方法返回原对象T,所以可以继续调用下一个.With()方法,完美实现流畅的链式语法。
内容的提问来源于stack exchange,提问作者Vinicius Andrade
相关产品推荐
相关产品推荐

