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

如何创建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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:10:30