Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get a variable's name as it was physically typed in its declaration? [duplicate]

People also ask

Can you have duplicate variable names in a project C#?

Essentially, it's not allowed because, in C#, their scopes actually do overlap.

How do you print a variable name in Python?

Using f-strings in Python to print variables is the most commonly used method and I would personally recommend using this method. In this method, an 'f' is placed before the opening quotation mark of a string. Braces {} are placed around the names of variables that you are looking to print.


Maybe you need this. Works fine.

I found this here.

static void Main(string[] args)
{
    var domain = "matrix";
    Check(() => domain);
    Console.ReadLine();
}

static void Check<T>(Expression<Func<T>> expr)
{
    var body = ((MemberExpression)expr.Body);
    Console.WriteLine("Name is: {0}", body.Member.Name);
    Console.WriteLine("Value is: {0}", ((FieldInfo)body.Member)
   .GetValue(((ConstantExpression)body.Expression).Value));
}

Output will be:

Name is: 'domain'
Value is: 'matrix'

I know this is old question, but I was trying to achieve the same and google sent me here. After many hours I finally found a way. I hope somebody else will find this useful.

There are actually more ways to accomplish this:

static void Main(string[] args) 
{
  GetName(new { var1 });
  GetName2(() => var1);
  GetName3(() => var1);
}

static string GetName<T>(T item) where T : class 
{
  return typeof(T).GetProperties()[0].Name;
}

static string GetName2<T>(Expression<Func<T>> expr) 
{
  return ((MemberExpression)expr.Body).Member.Name;
}

static string GetName3<T>(Func<T> expr) 
{
  return expr.Target.GetType().Module.ResolveField(BitConverter.ToInt32(expr.Method.GetMethodBody().GetILAsByteArray(), 2)).Name;
}

The first is fastest. The last 2 are approx 20 times slower than the 1st one.

http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html


city in this case is an instance of type string. When you call .GetType() you return the actual string type, which has no knowledge at all of your particular city instance.

I'm having a hard time seeing why you can't just type "city" in the code as a string literal here, if that's what you need. Perhaps it would help if you shared what you want to use this value for and in what circumstances you will call your DoSomething() function.

At the moment, my best guess is that what you really want to do is reflect the entire Person class to get a list of the fields in that class:

public void DoSomething()
{
    MemberInfo[] members = this.GetType().GetMembers();

    // now you can do whatever you want with each of the members,
    // including checking their .Name properties.
}

Okay, based on your edit I have some more for you.

You can find the name of fields that are decorated with your attribute at run-time like this:

Type t = typeof(Person);
foreach (MemberInfo member in t.GetMembers()
          .Where(m => 
                m.GetCustomAttributes(typeof(MyCustomAttribute)).Any()  ) )
{
    // "member" is a MemberInfo object for a Peson member that is 
    // decorated with your attribute
}

You can also use binding flags in the first GetMembers() call to limit it to just fields, if you want.


You mentioned "i.e. I need to get the string "city" from an instance of the object city." Are you looking to get the field name from the value of the field. For example:If there are 2 Person object one with city "New York" and the other with city "London", are you looking for the function to return "city". Is this what you mean by dynamic?


With your current design you will always need to compare the name of the field from the FieldInfo against a string. What if you instead decouple this so that you hold the identifier to use for comparison purposes during reflection as part of the attribute. Something like this:

 public enum ReflectionFields
{
    CITY = 0,
    STATE,
    ZIP,    
    COUNTRY

}

[AttributeUsage(AttributeTargets.Field,AllowMultiple=false)]
public class CustomFieldAttr : Attribute
{
    public ReflectionFields Field { get; private set; }
    public string MiscInfo { get; private set; }

    public CustomFieldAttr(ReflectionFields field, string miscInfo)
    {
        Field = field;
        MiscInfo = miscInfo;
    }
}

public class Person
{
    [CustomFieldAttr(ReflectionFields.CITY, "This is the primary city")]
    public string _city = "New York";

    public Person()
    {
    }
    public Person(string city)
    {
        _city = city;
    }

}

public static class AttributeReader<T> where T:class
{
    public static void Read(T t)
    {
        //get all fields which have the "CustomFieldAttribute applied to it"
        var fields = t.GetType().GetFields().Where(f => f.GetCustomAttributes(typeof(CustomFieldAttr), true).Length == 1);

        foreach (var field in fields)
        {
            var attr = field.GetCustomAttributes(typeof(CustomFieldAttr), true).First() as CustomFieldAttr;
            if (attr.Field == ReflectionFields.CITY)
            {
                //You have the field and you know its the City,do whatever processing you need.
                Console.WriteLine(field.Name);
            }
        }            
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        PPerson p1 = new PPerson("NewYork");
        PPerson p2 = new PPerson("London");
        AttributeReader<PPerson>.Read(p1);
        AttributeReader<PPerson>.Read(p2);

}
 }

You can now freely rename _city field of Person to something else and your calling code will still work since the code using reflection is trying to identify the field using the ReflectionFields enum value set as part of initialization of the attribute set on the field.


Yes its possible !!!

Try this out...

  public string DoSomething(object city)
  {
       return city.GetType().GetProperty("Name",typeof(string)).GetValue(city,null);
  }

Two things here.

Number one, as someone above pointed out, you're getting the Type for string, not for Person. So typeof(Person).GetMembers() will get you the list of members.

Number two, and more importantly, it looks like you're misunderstanding the purpose of attributes. In general attributes are used to mark a member for specific processing or to add additional information. Here you're using the name to indicate what processing you want, and the attribute to specify parameters, which is mixing of metaphors, or something.

Abhijeet's answer is more appropriate, you mark the field as a city field, then do what you like with it. Where I disagree is that I would use different attribute classes, rather than an enumeration.

Something like:

    public class MyAttribute : Attribute
    {

    }

    [AttributeUsage(AttributeTargets.Field)]
    public class MyCityAttribute : MyAttribute
    {
    }

    [AttributeUsage(AttributeTargets.Field]
    public class MyNameAttribute: MyAttribute
    {
    }

    public class Person
    {

        [MyCity]
        public string city = "New York";

        [MyCity]
        public string workCity = "Chicago";

        [MyName]
        public string fullName = "John Doe";

        public Person()
        {
        }


        public void DoSomething()
        {
            Type t = typeof(Person);
            FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public);

            foreach (var field in fields)
            {
                MyAttribute[] attributes = field.GetCustomAttributes(typeof(MyAttribute));
                if (attributes.Count > 0)
                {
                    if (attributes[0] is MyCityAttribute)
                    {
                        //Dosomething for city
                        break;
                    }

                    if (attributes[0] is MyNameAttribute)
                    {
                        //Dosomething for names
                        break;
                    }
                }
            }
        }
    }

This would allow you to use different parameters for MyCity vs MyName that would make more sense in the context of processing each.

I think with your 'yuk' comment above, you hit the nail on the head. That you would have to change a string constant if you rename your variable is an indicator that you're doing something wrong.