在类中,我有一个静态方法,通过提供表达式来获取PropertyInfo。
public static PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> expressie)
{
MemberExpression me;
switch (expressie.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = expressie.Body as UnaryExpression;
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
break;
default:
me = expressie.Body as MemberExpression;
break;
}
if (me == null)
{
throw new InvalidOperationException("Expression does not refer to a property: " + expressie.ToString());
}
return (PropertyInfo)me.Member;
}
为了让我的代码更安全,我更改了我在调用此函数的部分方法中使用的表达式。
// Old
Expression<Func<T, Object>> expression;
// New (TProp instead of Object)
Expression<Func<T, TProp>> expression;
因此,我无法使用旧版的GetPropertyInfo&#39;方法,因为表达式与请求的参数不匹配。所以我创建了一个新的。
public static PropertyInfo GetPropertyInfo<T, TProp>(Expression<Func<T, TProp>> expressie)
{
MemberExpression me;
switch (expressie.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = expressie.Body as UnaryExpression;
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
break;
default:
me = expressie.Body as MemberExpression;
break;
}
if (me == null)
{
throw new InvalidOperationException("Expression does not refer to a property: " + expressie.ToString());
}
return (PropertyInfo)me.Member;
}
这个新表达式的主体与现有表达式完全相同。因为我想坚持使用DRY原则,所以我搜索了一种方法,在两种情况下使用一个方法体。这可以通过首先转换&lt;表达式&lt; Func&lt; T,TProp&gt;&gt;&#39;进入&#39;表达&lt; Func&lt; T,对象&gt;&gt;&#39;并将转换后的表达式传递给&#39; old&#39; GetPropertyInfo(...)方法。我无法完全删除旧的&#39; GetPropertyInfo&#39;方法,因为其他代码仍然依赖它。
我使用的转换方法如下:
private static Expression<Func<T, object>> convertToObjectExpression<T, TProp>(Expression<Func<T, TProp>> expression)
{
return Expression.Lambda<Func<T,object>>(
Expression.Convert(expression.Body, typeof(object)),
expression.Parameters);
}
这很好用,除非我使用带有可空的DateTime(DateTime?)的表达式作为TProp的类型。在这种情况下,以下行会导致我&#39;为空。
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
有人知道会导致这个问题的原因吗?
我有fiddle包含问题。
答案 0 :(得分:2)
我建议你走另一条路。不要从新的类型安全方法转发到旧类型(包含所有附加问题),但是从旧方法转换到新方法:
// relay old interface to new one for compatibility
public static PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> expressie)
{
return GetPropertyInfo<T, object>(expressie);
}
public static PropertyInfo GetPropertyInfo<T, TProp>(Expression<Func<T, TProp>> expressie)
{ /* your code, as you provided it */ }
如果您仍然遇到此问题,请提供您的致电代码
修改强>
因与问题无关而被删除
答案 1 :(得分:1)
有人知道会导致这个问题的原因吗?
您调用新功能的方式(从普通DateTime
属性投射convertToObjectExpression
)以及实施方式(通过Convert
)会导致两个{{1}表达式,因此问题。
为了解决此问题,请考虑用户 grek40 建议,和/或更改实施,如下所示
public static PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> expressie)
{
var body = expressie.Body;
while (body.NodeType == ExpressionType.Convert || body.NodeType == ExpressionType.ConvertChecked)
body = ((UnaryExpression)body).Operand;
var me = body as MemberExpression;
var property = me != null ? me.Member as PropertyInfo : null;
if (property == null)
{
throw new InvalidOperationException("Expression does not refer to a property: " + expressie.ToString());
}
return property;
}