如何简化泛型调用?省略冗长的PropertyHelper属性获取代码
问题描述
我现有一段调用代码:
AddConversion<string>( PropertyHelper<PlayerCreditsBalanceWriter>.GetProperty(x => x.Credits), i => (long)i + ".0" );
希望简化为以下形式:
AddConversion<string>(x => x.Credits, i => (long)i + ".0" );
请问如何通过传递当前类的方式,避免使用冗长的PropertyHelper<T>.GetProperty代码?
附PropertyHelper类实现:
public static class PropertyHelper<T> { public static PropertyInfo GetProperty<TValue>( Expression<Func<T, TValue>> selector) { Expression body = selector; if (body is LambdaExpression) { body = ((LambdaExpression)body).Body; } return body.NodeType switch { ExpressionType.MemberAccess => (PropertyInfo)((MemberExpression)body).Member, _ => throw new InvalidOperationException() }; } }
解决方案
核心思路是让AddConversion直接接收属性选择器表达式,内部自动完成PropertyInfo的提取,无需外部显式调用PropertyHelper。
方法1:重载AddConversion方法
假设原AddConversion方法签名如下(基于调用逻辑推断):
public void AddConversion<TResult>(PropertyInfo property, Func<object, TResult> converter)
新增泛型重载方法,内部调用PropertyHelper获取属性信息后转发给原方法:
// 基础重载,适配object类型返回的属性选择器 public void AddConversion<T, TResult>(Expression<Func<T, object>> propertySelector, Func<object, TResult> converter) { var propertyInfo = PropertyHelper<T>.GetProperty(propertySelector); AddConversion<TResult>(propertyInfo, converter); } // 精确类型重载,避免值类型装箱 public void AddConversion<T, TValue, TResult>(Expression<Func<T, TValue>> propertySelector, Func<object, TResult> converter) { var propertyInfo = PropertyHelper<T>.GetProperty(propertySelector); AddConversion<TResult>(propertyInfo, converter); }
此时即可直接用目标形式调用,编译器会自动推断x的类型为PlayerCreditsBalanceWriter:
AddConversion<string>(x => x.Credits, i => (long)i + ".0");
方法2:内联属性提取逻辑
如果不想依赖PropertyHelper,可以将提取PropertyInfo的逻辑直接写到重载方法中:
public void AddConversion<T, TResult>(Expression<Func<T, object>> propertySelector, Func<object, TResult> converter) { Expression body = propertySelector.Body; // 处理值类型转object的装箱转换 if (body is UnaryExpression unary && unary.NodeType == ExpressionType.Convert) { body = unary.Operand; } if (body is MemberExpression memberExpr && memberExpr.Member is PropertyInfo propertyInfo) { AddConversion<TResult>(propertyInfo, converter); } else { throw new InvalidOperationException("表达式必须是属性访问"); } }
补充说明
- 若
AddConversion是静态方法,只需将重载也改为静态,并调整类的访问权限即可。 - 编译器会根据传入的属性选择器自动推断泛型参数
T,无需手动指定。
内容的提问来源于stack exchange,提问作者user5405648
相关产品推荐
相关产品推荐

