FastProperty 高效的属性读写设置
FastProperty
是一个设计精良、性能优异的工具类,很好地解决了批量操作中属性访问的性能问题,核心逻辑经得起推敲。对于 EFCore.BulkExtensions 的主要应用场景,它已经足够 “完美”。
/// <summary>
/// 使用反射初始化类型的类
/// </summary>
public class FastProperty
{// 用于缓存FastProperty实例的并发字典,确保线程安全private static readonly ConcurrentDictionary<PropertyInfo, FastProperty> FastPropertyCache = new();/// <summary>/// 获取或创建用于读写指定属性的FastProperty实例/// </summary>/// <param name="property">要获取FastProperty实例的属性</param>/// <returns>/// 新的或已存在的缓存中的FastProperty实例/// </returns>public static FastProperty GetOrCreate(PropertyInfo property){return FastPropertyCache.GetOrAdd(property, p => new FastProperty(p));}// 获取属性值的委托private Func<object, object>? _getDelegate;// 设置属性值的委托private Action<object, object>? _setDelegate;/// <summary>/// FastProperty的构造函数/// </summary>/// <param name="property">属性信息</param>private FastProperty(PropertyInfo property){Property = property;InitializeGet();InitializeSet();}/// <summary>/// 初始化属性设置委托/// </summary>private void InitializeSet(){var instance = Expression.Parameter(typeof(object), "instance");var value = Expression.Parameter(typeof(object), "value");if (Property.DeclaringType is null){throw new ArgumentException("无法从属性中确定声明类型(DeclaringType)");}// 根据属性声明类型是值类型还是引用类型,选择不同的转换方式UnaryExpression instanceCast = (!Property.DeclaringType?.IsValueType ?? false)? Expression.TypeAs(instance, Property.DeclaringType!): Expression.Convert(instance, Property.DeclaringType!);// 根据属性类型是值类型还是引用类型,选择不同的转换方式UnaryExpression valueCast = (!Property.PropertyType.IsValueType)? Expression.TypeAs(value, Property.PropertyType): Expression.Convert(value, Property.PropertyType);// 获取属性的set方法(支持非公共方法),处理继承自父类的属性场景var setter = Property.GetSetMethod(true) ?? Property.DeclaringType?.GetProperty(Property.Name)?.GetSetMethod(true);if (setter != null)// 编译表达式为设置属性的委托_setDelegate = Expression.Lambda<Action<object, object>>(Expression.Call(instanceCast, setter, valueCast), new ParameterExpression[] { instance, value }).Compile();}/// <summary>/// 初始化属性获取委托/// </summary>private void InitializeGet(){var instance = Expression.Parameter(typeof(object), "instance");if (Property.DeclaringType is null){throw new ArgumentException("无法从属性中确定声明类型(DeclaringType)");}// 根据属性声明类型是值类型还是引用类型,选择不同的转换方式UnaryExpression instanceCast = (!Property.DeclaringType.IsValueType)? Expression.TypeAs(instance, Property.DeclaringType): Expression.Convert(instance, Property.DeclaringType);// 获取属性的get方法(支持非公共方法),处理继承自父类的属性场景var getter = Property.GetGetMethod(true) ?? Property.DeclaringType.GetProperty(Property.Name)?.GetGetMethod(true);if (getter != null)// 编译表达式为获取属性的委托_getDelegate = Expression.Lambda<Func<object, object>>(Expression.TypeAs(Expression.Call(instanceCast, getter), typeof(object)), instance).Compile();}public PropertyInfo Property { get; set; }/// <summary>/// 返回属性值/// </summary>/// <param name="instance">实例对象</param>/// <returns>属性值</returns>public object? Get(object instance) => instance == default || _getDelegate is null ? default : _getDelegate(instance);/// <summary>/// 设置属性值/// </summary>/// <param name="instance">实例对象</param>/// <param name="value">要设置的值</param>public void Set(object instance, object? value){if (value != default && _setDelegate is not null){_setDelegate(instance, value);}}
}
使用示例:
var property = typeof(MyEntity).GetProperty("Id");
var fastProp = FastProperty.GetOrCreate(property);
var entity = new MyEntity { Id = Guid.NewGuid() };// 高效获取属性值
var id = fastProp.Get(entity);
// 高效设置属性值
fastProp.Set(entity, Guid.NewGuid());
总结
FastProperty
是 EFCore.BulkExtensions 性能优化的关键组件之一,它通过:
- 表达式树编译委托替代反射,解决了反射性能瓶颈;
- 线程安全缓存避免重复计算,降低初始化开销;
- 简洁接口简化属性访问逻辑,支撑了批量操作中的高频属性读写需求。