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

如何通过Lambda表达式决定要处理的Person类属性?

解决方案

要实现用Lambda指定要裁剪的属性,核心是要同时获取属性的读取、写入能力以及属性名称——普通的Func<Person, string>只能读取值,做不到动态赋值和获取属性名,这里用**表达式树(Expression)**就能完美解决:

实现思路

  1. 将扩展方法的参数改为Expression<Func<Person, string>>,通过表达式树解析目标属性的元数据;
  2. 从表达式中提取PropertyInfo,用它来获取属性名、读取当前值、写入裁剪后的值;
  3. 把裁剪逻辑和日志输出统一封装,完全符合DRY原则。

完整重构代码

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public static class PersonExtension
{   
    public static void TrimName(this Person person, Expression<Func<Person, string>> propertySelector)
    {
        // 解析表达式,提取目标属性的元数据
        if (propertySelector.Body is not MemberExpression memberExpr || 
            memberExpr.Member is not System.Reflection.PropertyInfo propInfo)
        {
            throw new ArgumentException("请传入有效的Person属性选择表达式");
        }

        var propertyName = propInfo.Name;
        Console.WriteLine($"Start Trim {propertyName}");

        // 安全读取属性值、裁剪后重新赋值
        var currentValue = propInfo.GetValue(person) as string;
        var trimmedValue = currentValue?.Length > 32 ? currentValue.Remove(32) : currentValue;
        propInfo.SetValue(person, trimmedValue);

        Console.WriteLine($"End Trim {propertyName}");
    }
}

public class Program
{
    public static void Main()
    {
        var person = new Person { FirstName = "Foo", LastName = "Bar" };
        
        // 调用时直接传入属性选择Lambda即可
        person.TrimName(x => x.FirstName);
        person.TrimName(x => x.LastName);
    }
}

补充说明

  • 表达式树能自动解析出属性名,不用硬编码,彻底避免重复代码;
  • 代码里优化了Remove(32)的风险:如果原字符串长度小于32,直接保留原内容,不会抛出异常;
  • 要是不想用表达式树,也可以传递两个委托(一个读、一个写),但调用会繁琐很多,示例如下:
public static void TrimName(this Person person, Func<Person, string> getter, Action<Person, string> setter, string propertyName)
{
    Console.WriteLine($"Start Trim {propertyName}");
    var value = getter(person);
    setter(person, value?.Length >32 ? value.Remove(32) : value);
    Console.WriteLine($"End Trim {propertyName}");
}

// 调用时需要手动传属性名
person.TrimName(p => p.FirstName, (p,v) => p.FirstName=v, nameof(Person.FirstName));

显然表达式树的方案更简洁可靠,是这类场景的首选。

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:55