Можно ли написать оболочку для оператора nameof C #? - PullRequest
0 голосов
/ 25 сентября 2019

Я прочитал связанный вопрос и ответ об операторе nameof, но это не помогло мне, поэтому я спросил об этом здесь.

Я хочу написать оболочку дляоператор C # nameof, поэтому он не только вернет имя свойства класса, но и объединит его с именем класса.

Предположим, класс с единственным свойством:

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

Теперь, если компилировать Console.WriteLine(nameof(Foo.SomeProperty)) с (C # 6 или выше) , результат будет:

SomeProperty

Так что это такможно получить что-то вроде этого:

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

Я поставил ???? для ввода Type, потому что я не знаю, что такое правильный ввод Type.

IЯ хочу, чтобы результат PrintFullName был:

Foo.SomeProperty

Я не обязательно ищу решения run времени.Любой обход компиляции также поможет.

Ответы [ 2 ]

2 голосов
/ 25 сентября 2019

Конечно, это возможно, используя деревья выражений.

Полное объяснение на этом сайте (все кредиты Дэйва Глика).

Это сводится к следующему:

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));
1 голос
/ 25 сентября 2019

Простое (и, возможно, более быстрое) решение без деревьев выражений (в которых используется отражение):

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

Использование:

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

nameof() - это конструкция времени компиляциипоэтому нет необходимости создавать слегка продвинутое решение, которое выполняет оценку во время выполнения больше, чем требуется.

...