これを行うことが可能です:
public static void SomeMethod<TFunc>(Expression<TFunc> expr)
{
//LambdaExpression happily excepts any Expession<TFunc>
LambdaExpression lamb = expr;
}
パラメータのラムダを渡して他の場所で呼び出します。
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"
私の目標は、属性のコンストラクターでメソッドまたはラムダを指定することです(完全な名前のメソッドを宣言し、メソッドの名前をなんらかの方法で渡す必要がある場合でも、それで問題ありません)。
パラメーターの型は変更できますが、属性コンストラクターがそのパラメーターを受け取り、何らかの方法でLambdaExpression型のフィールドに割り当てることができることが重要です。
ラムダ/メソッドの宣言を属性コンストラクターの呼び出しのすぐ上、つまりインラインにして、何が渡されているかを確認するために遠くまで行く必要がないようにします。
したがって、これらの代替手段は問題ありませんが、それらを機能させることはできません。
public static ... FuncName(...){...}
[ExpandableQueryAttribute(FuncName)]
// ...
また
//lambdas aren't allowed inline for an attribute, as far as I know
[ExpandableQueryAttribute(q => q.FirstOrDefault())]
// ...
既存の回避策は、コンストラクターに数値IDを渡すことです(「引数は定数でなければならない」要件を満たします)。これは、以前に式が追加された辞書でルックアップを実行するためにコンストラクターによって使用されます。これを改善/簡素化することを望んでいましたが、属性コンストラクターの制限により、これ以上改善されないと感じています。