You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现类似PHP eval功能 校验对象与数据库存储属性比较表达式是否匹配

C# 实现动态校验属性比较表达式方案

核心思路

使用Roslyn C#脚本引擎实现动态表达式解析执行,支持任意合法的C#属性比较逻辑,同时通过表达式缓存优化重复调用的性能。

前置依赖

首先安装所需NuGet包:

Install-Package Microsoft.CodeAnalysis.CSharp.Scripting

完整实现代码

using System;
using System.Collections.Concurrent;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

public class ExpressionEvaluator
{
    // 缓存已编译的表达式委托,避免重复编译损耗性能
    private static readonly ConcurrentDictionary<string, Func<object, bool>> _expressionCache = new();

    public static bool CheckMatch(object payment, string stringToCheck)
    {
        // 拼接缓存key,避免不同逻辑的表达式冲突
        var cacheKey = $"{payment.GetType().FullName}|{stringToCheck}";
        
        var evalFunc = _expressionCache.GetOrAdd(cacheKey, key =>
        {
            // 构造脚本执行的全局上下文
            var scriptOptions = ScriptOptions.Default
                // 添加上下文需要的程序集引用,可根据实际需求扩展
                .AddReferences(payment.GetType().Assembly)
                .AddImports("System");
            
            // 构造可执行的表达式脚本,用dynamic适配不同类型的输入对象
            var script = $"((dynamic)Payment).{stringToCheck}";
            
            // 编译为委托
            return CSharpScript.EvaluateAsync<Func<object, bool>>(
                @"return (Payment) => " + script + ";",
                scriptOptions
            ).Result;
        });
        
        // 执行委托返回结果
        return evalFunc(payment);
    }
}

// 示例业务类
public class PaymentInfo
{
    public long UidAsLong { get; set; }
    public string Name { get; set; }
}

使用示例

// 测试实例
var testPayment = new PaymentInfo
{
    UidAsLong = 18,
    Name = "Visa"
};

// 测试表达式1,输出True
Console.WriteLine(ExpressionEvaluator.CheckMatch(testPayment, "UidAsLong == 18"));
// 测试表达式2,输出True
Console.WriteLine(ExpressionEvaluator.CheckMatch(testPayment, "Name.Equals('Visa')"));
// 测试组合表达式,输出True
Console.WriteLine(ExpressionEvaluator.CheckMatch(testPayment, "UidAsLong > 10 && Name.StartsWith('V')"));

注意事项

  • 安全风险提示:该实现会执行传入的任意C#表达式,请确保数据库中存储的表达式全部来自可信来源,禁止直接执行用户未校验的输入内容,避免代码注入风险。
  • 如果不需要支持任意动态类型,可将代码中的dynamic替换为明确的业务类型(比如PaymentInfo),可以获得更好的执行性能和类型校验。
  • 缓存策略可根据实际业务调整,比如添加过期时间清理不常用的表达式。

内容的提问来源于stack exchange,提问作者Rodrigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 20:57:01