2

I have a class

public class MyCoolProp
{
    public string FullName {get;set;}
}

and in another Class i have this as Property:

public class MyMainClass
{
    public MyCoolProp coolprop {get;set;}

    public void DoSomething()
    {
        MessageBox.Show(nameof(coolprop.FullName));
    }
}

The Actual Result is: "Fullname"

But i want a combination like this: "coolprop.FullName"

i dont want to do something like this:

nameof(coolprop) + "." + nameof(coolprop.FullName);

Maybe its possible in an extension?

If i rename the Property "coolprop" the output should also have the new name

  • I believe this might be a duplicate of [this](https://stackoverflow.com/questions/40855818/how-to-use-nameof-to-get-the-fully-qualified-name-of-a-property-in-a-class-in-c) which basically says you cannot. – PhilMasteG Jun 02 '22 at 09:46
  • 1
    @PhilMasteG: That was back in 2016 - for *some* cases, the C# 10 feature of `CallerArgumentExpression` may be useful. – Jon Skeet Jun 02 '22 at 09:50

3 Answers3

7

Depending on exactly what you want to do, you might be able to use CallerArgumentExpressionAttribute. That does mean you need to be willing to actually evaluate the property as well, even if you don't use it.

Note that this requires a C# 10 compiler.

Here's a complete example:

using System.Runtime.CompilerServices;

public class MyCoolProp
{
    public string FullName { get; set; }
}

class Program
{
    static MyCoolProp CoolProp { get; set; }

    static void Main()
    {
        CoolProp = new MyCoolProp { FullName = "Test" };
        WriteTextAndExpression(CoolProp.FullName);
    }

    static void WriteTextAndExpression(string text,
        [CallerArgumentExpression("text")] string expression = null)
    {
        Console.WriteLine($"{expression} = {text}");
    }
}

Output: CoolProp.FullName = Test

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

Source: get name of a variable or parameter (modified a bit adjusted with your case)

You can use what System.Linq.Expression provides code example:

using System.Linq.Expression
class Program
{
    public static MyCoolProp coolProp { get; set; }
    static void Main(string[] args)
    {
        coolProp = new MyCoolProp() { FullName = "John" };
        DoSomething();
    }

    public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
    {
        MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
        return expressionBody.ToString();
    }

    public static void DoSomething()
    {
        string prop = GetMemberName(() => coolProp.FullName);
        Console.WriteLine(prop);
    }

}

public class MyCoolProp
{
    public string FullName { get; set; }
}

the GetMemberName method will return the namespace, class name, object name, and variable name (depends where the method is being called)

Output: Program.coolProp.FullName

Kim
  • 171
  • 6
0

Inspired by @kim's linq expression solution, here's an implementation that is hopefully a closer match to the nameof(XXX.YYY) that the OP was wanting. In particular..

  • Doesn't require an object instance, i.e. works directly against the types similar to nameof()
  • Also, it doesn't rely on ToString() to generate the full name, i.e. hopefully less brittle
public static string Of<T>(Expression<Func<T, object>> expression)
{
    static MemberExpression GetMemberExpression(Expression expression) =>
        expression as MemberExpression ?? (expression as UnaryExpression)?.Operand as MemberExpression;

    var names = new Stack<string>();
    var memberExpression = GetMemberExpression(expression.Body);

    while (memberExpression != null)
    {
        names.Push(memberExpression.Member.Name);
        memberExpression = GetMemberExpression(memberExpression.Expression);
    }

    names.Push(expression.Parameters.First().Type.Name);

    return string.Join(".", names);
}

Usage..

public class MyCoolProp
{
    public string FullName {get;set;}
    public CoolerProp AnotherProp { get; set; }
}

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

[Test]
public void Test()
{
    Assert.That(Name.Of<MyCoolProp>(x => x.FullName), Is.EqualTo("MyCoolProp.FullName"));
    Assert.That(Name.Of<MyCoolProp>(x => x.AnotherProp.Name), Is.EqualTo("MyCoolProp.AnotherProp.Name"));
}

stoj
  • 1,116
  • 1
  • 14
  • 25