【发布时间】:2020-06-25 02:09:41
【问题描述】:
所以我阅读了如何使用 Roslyn evaluate expressions 的方法,我想知道这是否可能以及如何将表达式限制为一组基本的数学运算和对我提供的一组减少的类型的运算(没有控制台.Writeline、单例、外部 Dll 等)。如何强制和检查 Roslyn 表达式的这种表达能力减少?
【问题讨论】:
标签: c# .net expression roslyn side-effects
所以我阅读了如何使用 Roslyn evaluate expressions 的方法,我想知道这是否可能以及如何将表达式限制为一组基本的数学运算和对我提供的一组减少的类型的运算(没有控制台.Writeline、单例、外部 Dll 等)。如何强制和检查 Roslyn 表达式的这种表达能力减少?
【问题讨论】:
标签: c# .net expression roslyn side-effects
一种可能的解决方案是将代码评估为表达式并分析表达式,例如Expression<Func<Album, bool>>.
Expression<Func<Album, bool>> discountFilterExpression = await CSharpScript.EvaluateAsync<Expression<Func<Album, bool>>>(discountFilter, options);
然后使用ExpressionVisitor 访问表达式的节点并检查表达式是否仅包含有效/允许的节点和类型。
例如,下面的访问者检查Math是否在评估的代码中被使用,如果是,则将表达式设置为无效:
class NoMathExpressionVisitor : ExpressionVisitor
{
public bool IsValid { get; private set; } = true;
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.DeclaringType == typeof(Math))
{
IsValid = false;
}
return base.VisitMethodCall(node);
}
}
总共:
// Generate expression
Expression<Func<Album, bool>> discountFilterExpression = await CSharpScript.EvaluateAsync<Expression<Func<Album, bool>>>(discountFilter, options);
// Visit each node using NoMathExpressionVisitor
var expressionVisitor = new NoMathExpressionVisitor();
expressionVisitor.Visit(discountFilterExpression);
// Check result
// For code: a => Math.Abs(a.Quality) > 10, IsValid returns false
if (expressionVisitor.IsValid)
{
// If the expression is valid, compile the expression to
// Func<> and run.
var result = discountFilterExpression.Compile()(album);
}
见https://docs.microsoft.com/en-us/dotnet/csharp/expression-trees-interpreting
【讨论】: