【发布时间】:2015-11-16 12:10:11
【问题描述】:
在一个类中,我有一个静态方法通过提供一个表达式来获取 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”方法,因为表达式与请求的参数不匹配。所以我创建了一个新的。
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 原则,所以我寻找了一种方法,在这两种情况下都使用一个方法体。这可以通过首先将 'Expression
我使用的转换方法如下:
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 类型。在这种情况下,以下行会导致 'me' 为空。
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
有没有人知道是什么导致了这个问题?
我有一个包含问题的fiddle。
【问题讨论】:
-
在调试模式下,能不能看一下“expressie.Body”的类型?可能不是 UnaryExpression。
-
这个函数怎么称呼?
-
“当我使用可以为空的 DateTime 的表达式时” - 你的意思是你将它与
DateTime?类型的属性或DateTime类型的属性一起使用转换为DateTime?. -
@IvanStoev 这确实是从 DateTime 属性到 DateTime 的转换?输入表达式。我需要这个,因为在其他地方我重新使用 TProp 类型来定义另一个参数的类型,有时它必须可以提供 null(实际上是 'default(DateTime?)')。
-
@KemalKefeli 表达式主体是 UnaryExpression 类型,并且强制转换 ('var ue = expressie.Body as UnaryExpression') 也不会导致 ue 为空。