【发布时间】:2012-06-15 19:44:04
【问题描述】:
可以这样做:
public static void SomeMethod<TFunc>(Expression<TFunc> expr)
{
//LambdaExpression happily excepts any Expession<TFunc>
LambdaExpression lamb = expr;
}
并在其他地方调用它并传递参数的 lambda:
SomeMethod<Func<IQueryable<Person>,Person>>( p=>p.FirstOrDefault());
我想将表达式作为参数传递给属性构造函数。 是否可以执行以下操作?
class ExpandableQueryAttribute: Attribute {
private LambdaExpression someLambda;
//ctor
public ExpandableQueryMethodAttribute(LambdaExpression expression)
{
someLambda = expression
}
}
//usage:
static LambdaExpression exp =
(Expression<Func<IQueryable<Person>, Person>>)
(p => p.FirstOrDefault());
[ExpandableQueryAttribute(exp)] //error here
// "An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type"
我的目标是在属性的构造函数中指定一个方法或 lambda(即使我必须声明一个完整的命名方法并以某种方式传递该方法的名称,也可以)。
参数类型可以改变,但重要的是属性构造函数可以采用该参数并以某种方式将其分配给 LambdaExpression 类型的字段
-
我希望 lambda/方法的声明刚好在对属性构造函数的调用之上,或者内联,这样您就不必走太远就能看到正在传递的内容。
所以这些替代方案会很好,但没有运气让它们起作用:
public static ... FuncName(...){...}
[ExpandableQueryAttribute(FuncName)]
// ...
或
//lambdas aren't allowed inline for an attribute, as far as I know
[ExpandableQueryAttribute(q => q.FirstOrDefault())]
// ...
现有的解决方法是将数字 ID 传递给构造函数(满足“参数必须是常量”的要求),构造函数使用它在先前添加了表达式的字典中进行查找。希望改进/简化这一点,但我觉得由于属性构造函数的限制,它并没有变得更好。
【问题讨论】:
-
按照你的感觉...属性参数的限制是相当明确的。
-
这个链接也有人问过这个问题。答案是目前不可能。 social.msdn.microsoft.com/Forums/en/vcsharp2008prerelease/…
-
@Jamey 是的,这是我列出的最后一个替代方案,我知道这是一个限制。希望通过将表达式声明为变量来解决这个问题,但是“必须保持不变”的要求让我着迷。不过,那里的解决方法很有趣,我将尝试一种变体。
标签: c# lambda custom-attributes