【问题标题】:How can I get/address the name of the calling property in my extension method如何在我的扩展方法中获取/寻址调用属性的名称
【发布时间】:2022-01-08 01:01:25
【问题描述】:

我正在尝试在我的扩展方法中获取调用属性的名称,以便在发生异常时使用它。

我的扩展方法如下:

/// <summary>
/// Parse string to value of T 
/// Can throw on Default or Exception
/// </summary>
/// <typeparam name="T">Type to Convert to</typeparam>
/// <param name="value">value for conversion</param>
/// <param name="throwOnDefault">set <see langword="true"/>for throw on Exception or Default</param>
/// <returns></returns>
/// <exception cref="NotSupportedException">If string can't be converted</exception>
/// <exception cref="Exception">If converted value is defaut</exception>
public static T ParseOrDefault<T>(this string value, bool throwOnDefault = false, [CallerMemberName]string methodName = "")
{
    if (Nullable.GetUnderlyingType(typeof(T)) == null && value.IsNullOrWhitespace()) 
        throw new ArgumentNullException(value, $"{methodName} : value of string is null");

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

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

        var type = converted?.GetType();

        if (type != null && type.IsValueType)
        {
            var defaultValue = Activator.CreateInstance(type);
            return !value.Equals(defaultValue) ? converted : throw new Exception("Converted value is default value");
        }
        else
        {
            return converted;
        }
    }
    catch (Exception)
    {
        if (throwOnDefault)
            throw;
        else
            return default;
    }
}

我正在这样使用它:

var parsedVal = property.ParseOrDefault<Guid>();

或者像这样:

public void SomeMethod (RequestModel request)
{
    Dto dto = new()
    {
        intProperty = request.IntValue.ParseOrDefault<int>(), // IntValue in the requestObject is a string 
        guidProperty = request.GuidValue.ParseOrDefault<Guid>() // GuidValue in the requestObject is a string
    }
}

我已经尝试了以下链接中的一些建议,但它们都只是让我得到调用方法的名称,而不是属性的名称。

How to get current property name via reflection?

我的目标是让我的异常看起来像这样的方法和属性:

if (Nullable.GetUnderlyingType(typeof(T)) == null && value.IsNullOrWhitespace()) 
        throw new ArgumentNullException(value, $"{methodName} : value of {propertyName} is null");

【问题讨论】:

  • 没有办法得到你想要的。您不必为属性编写扩展方法,而是为值编写扩展方法,一旦从属性中获取了值,该属性就不再涉及到表达式的其余部分。最多您可以从堆栈跟踪中获得表达式编写的位置,但您无法轻易确定该值是从哪个属性获得的。
  • 其实是有办法的。 @richard-deeming 帮助我实现了我想要的。我已经将其标记为答案。不过还是谢谢你帮忙^^

标签: c# .net


【解决方案1】:

[CallerMemberName] 将为您提供调用扩展方法的方法/属性的名称。在您的示例中,这将是 SomeMethod

如果您可以更新到 C# 10,则可以改用 the [CallerArgumentExpression] attribute

public static T ParseOrDefault<T>(this string value, bool throwOnDefault = false, [CallerArgumentExpression("value")] string memberName = "")

对于request.IntValue.ParseOrDefault&lt;int&gt;()memberName 将设置为request.IntValue

如果您使用的是 .NET Framework,you can still use this approach 只要您使用的是最新的编译器。您只需要手动定义属性类。

【讨论】:

  • 我正在使用最新版本的 gRPC 服务,并且映射和解析的东西非常麻烦。非常感谢您的快速回复。结果很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 2014-10-27
  • 1970-01-01
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
相关资源
最近更新 更多