1

我阅读了有关运营商的相关问答nameof但它对我没有帮助,所以我在这里问它。

我想为 C#nameof运算符编写一个包装器,这样它不仅会返回类属性的名称,而且还会将它与类名连接起来。

让我们假设一个具有单一属性的类:

class Foo
{
   public string SomeProperty {get; set;}
}

Console.WriteLine(nameof(Foo.SomeProperty))现在如果使用(C# 6 or higher)编译,结果将是:

一些财产

所以有可能有这样的东西:

public string PrintFullName(???? object)
{
    //????
}

????输入了输入Type,因为我不知道正确的输入Type是什么。

我希望 PrintFullName 的结果是:

Foo.SomeProperty

我不一定要寻找运行时解决方案。任何编译时解决方法也将有所帮助。

4

2 回答 2

2

当然这是可能的,使用表达式树。

网站上的完整说明(所有归功于 Dave Glick)。

归结为:

public void UseNames(string className, string memberName)
{
    // Your code to use the class & membername go here
}

public void UseNames<T>(Expression<Func<T, object>> expression)
{
    MemberExpression member = expression.Body as MemberExpression;
    if (member == null)
    {
        // The property access might be getting converted to object to match the func
        // If so, get the operand and see if that's a member expression
        member = (expression.Body as UnaryExpression)?.Operand as MemberExpression;
    }
    if (member == null)
    {
        throw new ArgumentException("Action must be a member expression.");
    }

    // Pass the names on to the string-based UseNames method
    UseNames(typeof(T).Name, member.Member.Name);
}

public void UseNames<T>(Expression<Func<T, string>> expression)
{
    ConstantExpression constant = expression.Body as ConstantExpression;
    if (constant == null)
    {
        throw new ArgumentException("Expression must be a constant expression.");
    }
    UseNames(typeof(T).Name, constant.Value.ToString());
}

像这样使用它:

UseNames<Foo>(x => nameof(x.Bar));
UseNames<Foo>(x => nameof(x.Baz));
于 2019-09-25T15:33:28.490 回答
1

一个简单(也许更快)的解决方案,没有表达式树(使用反射):

public string PrintFullName<T>(String memberName)
{
    return $"{typeof(T).Name}.{memberName}";
}

用法:

PrintFullName<SomeType>(nameof(SomeType.SomeProperty));
// Compiled to: PrintFullName<SomeType>("SomeProperty");

nameof()是一个编译时构造,因此无需构建一个稍微高级的解决方案,在运行时执行超出所需的评估。

于 2019-09-25T17:44:43.383 回答