有没有办法在表达式树中设置 'DeclaringType' ?
Is there a way to set 'DeclaringType' in an expression tree?
我正在进行 Func -> Expression -> Func 转换。如果我从一个方法(下面的第一个示例)创建 Func<>() 它工作正常但是如果我使用表达式树创建函数(第二个示例)它会失败并出现 NullReferenceException 当访问 func2.Method.DeclaringType.FullName。这是因为 DeclaringType 为空。 (NJection 使用反射,所以我认为这就是它需要 DeclaringType 的原因。)
如何为编译表达式树创建的Func<>填写DeclaringType类型? (也许不可能?)在第一个示例中设置了 DeclaringType。
使用方法中的 Func<>...(效果很好)
// Build a Func<>
Func<int, int> add = Add;
// Convert it to an Expression using NJection Library
Expression<Func<int, int>> expr = ToExpr<Func<int, int>>(add);
// Convert it back to a Func<>
Func < int, int> func = expr.Compile();
// Run the Func<>
int result = func(100);
使用表达式树(不起作用)...
// Build a Func<> using an Expression Tree
ParameterExpression numParam = Expression.Parameter(typeof(int));
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numAddFive = Expression.Add(numParam, five);
Func<int, int> func2 =
Expression.Lambda<Func<int, int>>(
numAddFive,
new ParameterExpression[] { numParam }).Compile();
// Convert to an Expression using NJection (EXCEPTION ON NEXT LINE)
// ToExpr is trying to access func2.Method.DeclaringType.FullName(DeclaringType is null)
Expression<Func<int, int>> exp2 = ToExpr<Func<int, int>>(func2);
// Convert it back to a Func<>
Func<int, int> func2b = exp2.Compile();
// Run the Func<>
int result2 = func2b(100);
我猜没有。
当您将表达式编译为可执行 Func 时,从技术上讲,它是一种动态方法。如果您要调用 func2.Method.GetType()
,您可以看到这一点。那 returns type DynamicMethod which always has null
as the Declaring Type.
我不知道 NJection 库的用途是什么,因为他们的网站已关闭,并且他们的 Codeplex 上没有可用的源代码。
如果你只需要得到一个可以编译回函数的Expression
,你可以自己创建它。例如。像这样:
static Expression<T> ToExpr<T>(T func)
{
var type = typeof(T);
var method = type.GetMethod("Invoke"); // Delegate.Invoke() has parameters types matching delegate parameters types
var pars = method.GetParameters()
.Select(pi => Expression.Parameter(pi.ParameterType))
.ToArray();
return Expression.Lambda<T>(
Expression.Call(Expression.Constant(func), method, pars),
pars
);
}
有了这个ToExpr
,你上面的代码编译和运行没有问题。
我正在进行 Func -> Expression -> Func 转换。如果我从一个方法(下面的第一个示例)创建 Func<>() 它工作正常但是如果我使用表达式树创建函数(第二个示例)它会失败并出现 NullReferenceException 当访问 func2.Method.DeclaringType.FullName。这是因为 DeclaringType 为空。 (NJection 使用反射,所以我认为这就是它需要 DeclaringType 的原因。)
如何为编译表达式树创建的Func<>填写DeclaringType类型? (也许不可能?)在第一个示例中设置了 DeclaringType。
使用方法中的 Func<>...(效果很好)
// Build a Func<>
Func<int, int> add = Add;
// Convert it to an Expression using NJection Library
Expression<Func<int, int>> expr = ToExpr<Func<int, int>>(add);
// Convert it back to a Func<>
Func < int, int> func = expr.Compile();
// Run the Func<>
int result = func(100);
使用表达式树(不起作用)...
// Build a Func<> using an Expression Tree
ParameterExpression numParam = Expression.Parameter(typeof(int));
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numAddFive = Expression.Add(numParam, five);
Func<int, int> func2 =
Expression.Lambda<Func<int, int>>(
numAddFive,
new ParameterExpression[] { numParam }).Compile();
// Convert to an Expression using NJection (EXCEPTION ON NEXT LINE)
// ToExpr is trying to access func2.Method.DeclaringType.FullName(DeclaringType is null)
Expression<Func<int, int>> exp2 = ToExpr<Func<int, int>>(func2);
// Convert it back to a Func<>
Func<int, int> func2b = exp2.Compile();
// Run the Func<>
int result2 = func2b(100);
我猜没有。
当您将表达式编译为可执行 Func 时,从技术上讲,它是一种动态方法。如果您要调用 func2.Method.GetType()
,您可以看到这一点。那 returns type DynamicMethod which always has null
as the Declaring Type.
我不知道 NJection 库的用途是什么,因为他们的网站已关闭,并且他们的 Codeplex 上没有可用的源代码。
如果你只需要得到一个可以编译回函数的Expression
,你可以自己创建它。例如。像这样:
static Expression<T> ToExpr<T>(T func)
{
var type = typeof(T);
var method = type.GetMethod("Invoke"); // Delegate.Invoke() has parameters types matching delegate parameters types
var pars = method.GetParameters()
.Select(pi => Expression.Parameter(pi.ParameterType))
.ToArray();
return Expression.Lambda<T>(
Expression.Call(Expression.Constant(func), method, pars),
pars
);
}
有了这个ToExpr
,你上面的代码编译和运行没有问题。