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

构建字符串转枚举的表达式树时遇ArgumentException异常,同时需实现异常信息中获取输入参数值

构建字符串转枚举的表达式树时遇ArgumentException异常,同时需实现异常信息中获取输入参数值

嗨,我来帮你梳理并解决这个问题~

先说说你遇到的异常原因

你碰到的System.ArgumentException核心问题在于:Expression.IfThenElse是一个无返回值(void类型)的表达式,它只负责执行两个分支的逻辑,但不会返回任何结果;而你要构建的Func<TString, TEnum> Lambda要求body必须返回TEnum类型的值,类型不匹配自然就报错了。

再解决两个核心需求:修复异常 + 异常消息包含输入值

我们需要做两个关键调整:

  1. 用**有返回值的分支表达式Expression.Condition**替代Expression.IfThenElse,让Lambda的body能返回正确类型的结果;
  2. 动态构建异常消息,通过表达式调用字符串格式化方法,把输入参数的值嵌入到异常描述里。

修正后的完整代码

public static Func<TString, TEnum> BuildStringToEnumConvertor<TString, TEnum>()
{
    var enumType = typeof(TEnum);
    var enumTypeExp = Expression.Constant(enumType);

    var dbValueExp = Expression.Parameter(typeof(TString), "dbValue");
    
    // 构建Enum.IsDefined的调用表达式
    var isDefinedMethod = typeof(Enum).GetMethod("IsDefined", new[] { typeof(Type), typeof(object) });
    var testExp = Expression.Call(null, isDefinedMethod, enumTypeExp, Expression.Convert(dbValueExp, typeof(object)));

    // 构建Enum.Parse的调用及转换逻辑
    var parseMethod = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string) });
    var strExp = Expression.Convert(Expression.Convert(dbValueExp, typeof(object)), typeof(string));
    var parsedExp = Expression.Call(null, parseMethod, enumTypeExp, strExp);
    var objExp = Expression.Convert(parsedExp, enumType);

    // 动态构建包含输入参数的异常消息
    var errorTemplate = Expression.Constant($"Could not convert '{{0}}' to type '{enumType.Name}'.");
    var formattedErrorMsg = Expression.Call(
        typeof(string), 
        "Format", 
        Type.EmptyTypes, 
        errorTemplate, 
        dbValueExp
    );
    // 创建异常表达式,并指定返回类型为TEnum(让分支类型匹配)
    var exceptionCtor = typeof(Exception).GetConstructor(new[] { typeof(string) });
    var throwExp = Expression.Throw(
        Expression.New(exceptionCtor, formattedErrorMsg),
        enumType
    );

    // 用Condition替代IfThenElse,确保有返回值
    var bodyExp = Expression.Condition(testExp, objExp, throwExp);

    // 构建并编译Lambda
    return Expression.Lambda<Func<TString, TEnum>>(bodyExp, dbValueExp).Compile();
}

internal enum TestEnum
{
    Age = 1,
    Name,
    Address,
    CellPhone,
    Max = 500
}

关键调整点说明

  • 替换IfThenElse为Condition:Expression.Condition会根据测试表达式的结果,返回两个分支中符合指定类型的结果,完美适配Lambda对返回值的要求;
  • 动态异常消息:通过Expression.Call调用string.Format,把输入参数dbValueExp作为格式化参数传入,这样异常消息就能动态包含实际的输入值;
  • 指定Throw的返回类型:Expression.Throw默认返回void,我们显式指定返回类型为TEnum,保证Condition的两个分支类型完全一致(都是TEnum),避免类型不匹配的问题。

测试效果

当你调用var func = BuildStringToEnumConvertor<string, TestEnum>();,然后执行func("InvalidValue");时,会抛出异常,异常消息会显示:Could not convert 'InvalidValue' to type 'TestEnum'.,完美包含了输入的参数值。

备注:内容来源于stack exchange,提问作者long

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 02:54:42