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

C#扩展方法如何获取调用方属性名以用于异常信息输出?

解决方案

方案1:使用CallerArgumentExpression特性(推荐,C# 10及以上版本支持)

这是最简单的实现方案,不需要修改任何现有调用代码,编译器会自动填充属性调用的表达式文本:
修改你的扩展方法,新增一个带[CallerArgumentExpression]特性的参数即可:

/// <summary>
/// 把字符串转换为T类型的值
/// 可配置转换失败或得到默认值时抛出异常
/// </summary>
/// <typeparam name="T">要转换的目标类型</typeparam>
/// <param name="value">待转换的字符串值</param>
/// <param name="throwOnDefault">设置为true时,转换失败或得到默认值会抛出异常</param>
/// <param name="methodName">调用方方法名,编译器自动填充</param>
/// <param name="propertyPath">调用方传入value的表达式,编译器自动填充</param>
/// <returns>转换后的值</returns>
/// <exception cref="NotSupportedException">字符串无法转换为目标类型时抛出</exception>
/// <exception cref="Exception">转换后得到目标类型默认值时抛出</exception>
public static T ParseOrDefault<T>(this string value, 
                                  bool throwOnDefault = false, 
                                  [CallerMemberName]string methodName = "",
                                  [CallerArgumentExpression(nameof(value))]string propertyPath = "")
{
    if (Nullable.GetUnderlyingType(typeof(T)) == null && string.IsNullOrWhiteSpace(value)) 
        // 注意:ArgumentNullException第一个参数是异常参数名,不要直接传value
        throw new ArgumentNullException(propertyPath, $"{methodName} : value of {propertyPath} is null");

    System.ComponentModel.TypeConverter converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));

    try
    {
        var converted = (T)converter.ConvertFromString(null, System.Globalization.CultureInfo.InvariantCulture, value);

        if (converted is ValueType val)
        {
            var defaultValue = Activator.CreateInstance(val.GetType());
            return !val.Equals(defaultValue) ? converted : throw new Exception($"{methodName} : Converted value of {propertyPath} is default value");
        }
        return converted;
    }
    catch (Exception)
    {
        if (throwOnDefault)
            throw;
        return default;
    }
}

调用方式和你原有代码完全一致,无需额外传参:

public void SomeMethod (RequestModel request)
{
    Dto dto = new()
    {
        intProperty = request.IntValue.ParseOrDefault<int>(), 
        guidProperty = request.GuidValue.ParseOrDefault<Guid>() 
    }
}

此时如果request.IntValue为空,抛出的异常信息会自动变成SomeMethod : value of request.IntValue is null,完全符合你的需求。

方案2:C# 10以下版本兼容方案

如果你的项目使用的C#版本低于10,无法使用CallerArgumentExpression特性,可以选择以下两种实现方式:

  • 手动传入属性名:调用时显式传入nameof参数,示例:
    intProperty = request.IntValue.ParseOrDefault<int>(propertyName: nameof(request.IntValue))
    
  • 基于表达式树封装扩展方法:无需手动传参,但运行时会有少量性能损耗,适合对性能要求不高的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 05:06:03