如何使用Expression.Lambda生成带返回值的函数?求技术指导
关于用Expressions生成FieldInfo赋值函数的解惑
其实你完全不用纠结“这是不是Expressions的设计初衷”——用它来替代反射实现高效的字段赋值,不仅完全合理,还是Expressions的典型应用场景之一!
先给你理清楚几个关键点:
- 你要做的生成运行时赋值函数,本质是把反射操作编译成强类型委托,比起直接调用
FieldInfo.SetValue,性能提升非常明显,尤其是需要多次给同类型实例赋值的场景,这也是很多高性能框架里常用的优化手段 - 如果你只是偶尔用一次,直接用
FieldInfo.SetValue确实更省事,但如果是高频调用,花点时间弄明白这个Expressions的用法绝对不亏
给你写个极简的实现示例,看完你应该就能明白怎么用它完成你的需求:
using System; using System.Reflection; using System.Linq.Expressions; public static class FieldSetterGenerator { public static Action<TObj, TVal> CreateSetter<TObj, TVal>(FieldInfo field) { // 定义两个参数:类实例和要设置的值 var instanceParam = Expression.Parameter(typeof(TObj), "obj"); var valueParam = Expression.Parameter(typeof(TVal), "val"); // 构建赋值表达式:obj.Field = val var assignExpression = Expression.Assign( Expression.Field(instanceParam, field), valueParam ); // 把表达式编译成可直接调用的委托 return Expression.Lambda<Action<TObj, TVal>>(assignExpression, instanceParam, valueParam).Compile(); } }
实际使用的例子也很简单:
// 假设我们有一个测试类 public class TestClass { public int MyField; private string _privateField; } // 获取字段的FieldInfo var publicField = typeof(TestClass).GetField("MyField"); var privateField = typeof(TestClass).GetField("_privateField", BindingFlags.Instance | BindingFlags.NonPublic); // 生成对应的赋值器 var publicSetter = FieldSetterGenerator.CreateSetter<TestClass, int>(publicField); var privateSetter = FieldSetterGenerator.CreateSetter<TestClass, string>(privateField); // 给实例赋值 var testInstance = new TestClass(); publicSetter(testInstance, 123); privateSetter(testInstance, "私有字段的值");
至于你担心的“是否大材小用”——Expressions的核心设计目标就是支持运行时构建、编译代码逻辑,反射场景的性能优化只是它的众多用法之一,你的需求完全在它的适用范围内。如果只是为了这个单一用途,你根本不用啃完所有Expressions的知识点,掌握参数表达式、字段访问、赋值表达式和Lambda编译这几个基础点就足够了。
要是你原本的计划还有其他内容,也可以补充出来,我再帮你针对性分析~
内容的提问来源于stack exchange,提问作者sebas
相关产品推荐
相关产品推荐

