如何限制表达式访问 Roslyn 中的外部类型?
How to limit expression access to types external in Roslyn?
所以我通读了如何使用 Roslyn evaluate expressions 的方法,我想知道这是否可能以及如何将表达式限制为一组基本数学运算以及对由提供的一组简化类型的运算我(没有 Console.Writeline、单例、外部 Dll 等)。如何强制和检查 Roslyn 表达式的这种表达式能力降低?
一种可能的解决方案是将代码评估为表达式并分析表达式,例如Expression<Func<Album, bool>>
.
Expression<Func<Album, bool>> discountFilterExpression = await CSharpScript.EvaluateAsync<Expression<Func<Album, bool>>>(discountFilter, options);
然后使用ExpressionVisitor
访问表达式的节点并检查表达式是否仅包含valid/allowed个节点和类型。
例如,下面的访问者检查是否在评估的代码中使用了 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
所以我通读了如何使用 Roslyn evaluate expressions 的方法,我想知道这是否可能以及如何将表达式限制为一组基本数学运算以及对由提供的一组简化类型的运算我(没有 Console.Writeline、单例、外部 Dll 等)。如何强制和检查 Roslyn 表达式的这种表达式能力降低?
一种可能的解决方案是将代码评估为表达式并分析表达式,例如Expression<Func<Album, bool>>
.
Expression<Func<Album, bool>> discountFilterExpression = await CSharpScript.EvaluateAsync<Expression<Func<Album, bool>>>(discountFilter, options);
然后使用ExpressionVisitor
访问表达式的节点并检查表达式是否仅包含valid/allowed个节点和类型。
例如,下面的访问者检查是否在评估的代码中使用了 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