.net 为什么nameof只返回姓氏?

ct3nt3jp  于 2023-04-13  发布在  .NET
关注(0)|答案(6)|浏览(126)

nameof(order.User.Age)只返回Age而不是order.User.Age
为什么要用更严格的方式呢?如果我们只需要姓氏,我们可以做一些类似的事情

public static GetLastName(this string x) { 
    return string.Split(x, '.').Last();
}

nameof(order.User.Age).GetLastName()

使用一个操作符,我们可以同时得到Ageorder.User.Age。但是在当前的实现中,我们只能得到Age。这个决定背后有什么逻辑吗?例如,这种行为对于MVC绑定是必要的

Html.TextBox(nameof(order.User.Age))
tnkciper

tnkciper1#

请注意,如果您需要/想要“完整”名称,您可以这样做:

$"{nameof(order)}.{nameof(User)}.{nameof(Age)}".GetLastName();

只要所有这些名称都在当前作用域中

显然,在这种情况下,它并没有那么有用(名称不在Razor调用的范围内),但是如果您需要,例如,调用Type.GetType()或其他东西的类型的完整命名空间限定名,它可能会有帮助。
如果名称不在作用域中,您仍然可以执行更笨拙的操作:

$"{nameof(order)}.{nameof(order.User)}.{nameof(order.User.Age)}".GetLastName();

--尽管可能至少有一个应该在范围内(除非User.Age是静态属性)。

r1zhe5dt

r1zhe5dt2#

我遇到了同样的问题,并实现了一个类,它作为nameof()关键字的替换,以获得所提供的表达式的全名。它受到OK HOSTING answer的极大启发。它只是全部烤好并准备用途:

public static class NameOf<TSource>
{
    #region Public Methods

    public static string Full(Expression<Func<TSource, object>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            var unaryExpression = expression.Body as UnaryExpression;
            if (unaryExpression != null && unaryExpression.NodeType == ExpressionType.Convert)
                memberExpression = unaryExpression.Operand as MemberExpression;
        }

        var result = memberExpression.ToString();
        result = result.Substring(result.IndexOf('.') + 1);

        return result;
    }

    public static string Full(string sourceFieldName, Expression<Func<TSource, object>> expression)
    {
        var result = Full(expression);
        result = string.IsNullOrEmpty(sourceFieldName) ? result : sourceFieldName + "." + result;
        return result;
    }

    #endregion
}

在代码中使用它看起来像这样:

class SpeciesFamily
{
    public string Name { get; set; }
}

class Species
{
    public SpeciesFamily Family { get; set; }
    public string Name { get; set; }
}

class Cat
{
    public Species Species { get; set; }
}

// Will return a string containing "Species.Family.Name".
var fullName = NameOf<Cat>.Full(c => c.Species.Family.Name);

// Will return a string containing "cat.Species.Name".
var fullNameWithPrefix = NameOf<Cat>.Full("cat", c => c.Species.Name);
snvhrwxg

snvhrwxg3#

正如你在已经链接的讨论中所读到的,这里你使用nameof运算符作为nameof(member-access),其形式为E.I<A1…AK>,它将返回:
这些情况都使用简单名称查找规则$7.6.2或成员访问规则$7.6.4解决。如果它们成功绑定,则必须绑定到以下之一:

  • 方法组。这将产生错误“若要指定方法的名称,必须提供其参数”。
  • 一个变量,值,参数,常量,枚举成员,属性访问,字段,事件,类型参数,命名空间或类型。在这种情况下,nameof运算符的结果只是“I”,这通常是参数绑定到的符号的名称。有一些注意事项...

所以在这种情况下,根据它的定义,它必须一步一步地评估所有点之前的所有表达式,然后评估最后一个表达式以获得它的Name

order.User.Age --> User.Age --> Age
2hh7jdfx

2hh7jdfx4#

看看这个方法,它来自:
https://github.com/okhosting/OKHOSTING.Data/blob/master/src/PCL/OKHOSTING.Data/Validation/MemberExpression.cs

public static string GetMemberString(System.Linq.Expressions.Expression<Func<T, object>> member)
    {
        if (member == null)
        {
            throw new ArgumentNullException("member");
        }

        var propertyRefExpr = member.Body;
        var memberExpr = propertyRefExpr as System.Linq.Expressions.MemberExpression;

        if (memberExpr == null)
        {
            var unaryExpr = propertyRefExpr as System.Linq.Expressions.UnaryExpression;

            if (unaryExpr != null && unaryExpr.NodeType == System.Linq.Expressions.ExpressionType.Convert)
            {
                memberExpr = unaryExpr.Operand as System.Linq.Expressions.MemberExpression;

                if(memberExpr != null)
                {
                    return memberExpr.Member.Name;
                }
            }
        }
        else
        {
            //gets something line "m.Field1.Field2.Field3", from here we just remove the prefix "m."
            string body = member.Body.ToString();
            return body.Substring(body.IndexOf('.') + 1);
        }

        throw new ArgumentException("No property reference expression was found.", "member");
    }
6fe3ivhb

6fe3ivhb5#

使用nameof的一些重要目的是获取表达式中的最后一个“名称”。
例如抛出ArgumentNullException时的参数名称:

void Method(string parameter)
{
     if (parameter == null) throw new ArgumentNullException(nameof(parameter));
}

MVC Action链接

<%= Html.ActionLink("Sign up",
    @typeof(UserController),
    @nameof(UserController.SignUp))
%>

INotifyPropertyChanged

int p {
    get { return this._p; }
    set { this._p = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.p)); }
}

更多信息:https://roslyn.codeplex.com/discussions/570551

628mspwn

628mspwn6#

.NET 6添加了CallerArgumentExpression,允许您创建fullnameof的解决方案版本。

using System.Runtime.CompilerServices;

var fullString = StringOf(nameof(HttpResponseMessage.Content.Headers));

// Prints: HttpResponseMessage.Content.Headers
Console.WriteLine(fullString);

static string StringOf(string value, [CallerArgumentExpression(nameof(value))] string fullpath = default!)
{
    // value is: "value"
    // fullpath is: "nameof(HttpResponseMessage.Content.Headers)"
    // Do some validation here...

    // Strip "nameof(", ... ")"
    string outputString = fullpath.Substring(fullpath.IndexOf("(") + 1, fullpath.IndexOf(")") - fullpath.IndexOf("(") - 1);

    return outputString;
}

相关问题