你如何得到一个variables的名称,因为它的声明是物理types的?

可能重复:
在C#中查找传递给函数的variables名

下面的课程包含实地城市。

我需要dynamic确定字段的名称,因为它是在类声明中键入的,即我需要从对象城市的实例中获取string“城市”。

我试图通过检查其在DoSomething()中的types来做到这一点,但在debugging器中检查types的内容时找不到它。

可能吗?

public class Person { public string city = "New York"; public Person() { } public void DoSomething() { Type t = city.GetType(); string field_name = t.SomeUnkownFunction(); //would return the string "city" if it existed! } } 

有些人在下面的答案中问我为什么要这样做。 这是为什么。

在我现实世界的情况下,城市上面有一个自定义的属性。

 [MyCustomAttribute("param1", "param2", etc)] public string city = "New York"; 

我需要在其他代码中的这个属性。 要获得属性,我使用reflection。 而在reflection代码我需要inputstring“城市”

 MyCustomAttribute attr; Type t = typeof(Person); foreach (FieldInfo field in t.GetFields()) { if (field.Name == "city") { //do stuff when we find the field that has the attribute we need } } 

现在这不是安全的。 如果我在Person中的字段声明中将variables“city”更改为“workCity”,则除非知道更新string,否则该行将失败

 if (field.Name == "workCity") //I have to make this change in another file for this to still work, yuk! { } 

所以我想find一些方法来传递string到这个代码没有物理input。

是的,我可以在Person(或类似的东西)中声明一个string常量,但是仍然会input两次。

唷! 这很难解释!

谢谢

感谢所有谁回答了这个*很多*。 它给了我一个新的途径,以更好地理解lambdaexpression式。 它创造了一个新的问题。

也许你需要这个。 工作正常。

我在这里find了 。

 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)); } 

输出将是:

名称是:'域'
价值是:'matrix'

我知道这是一个老问题,但我试图达到同样的,谷歌送我到这里。 几个小时后,我终于find了一个方法。 我希望别人会觉得这有用。

实际上有更多的方法来完成这个:

 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; } 

第一个是最快的。 最后2个比第一个慢大约20倍。

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

在这种情况下, city是一个stringtypes的实例 。 当你调用.GetType()你会返回实际的stringtypes,它并不知道你的特定城市实例。

我很难看到为什么你不能在代码中input“城市”作为string文字,如果这是你所需要的。 如果你分享了你想要使用这个值的情况,以及在什么情况下你会调用你的DoSomething()函数,也许会有所帮助。

此刻,我最好的猜测是,你真正想要做的是反映整个Person类,以获得该类中的字段列表:

 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. } 

好的,根据你的编辑,我还有一些你的。

您可以在运行时find用您的属性修饰的字段的名称,如下所示:

 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 } 

如果需要,还可以在第一个GetMembers()调用中使用绑定标志将其限制为仅字段。

你提到“即我需要从对象城市的实例获得string”城市“。 您是否希望从字段的值中获取字段名称? 例如:如果有两个Person对象,一个是城市“纽约”,另一个是城市“伦敦”,您是否在寻找返回“城市”的function。 这是你dynamic的意思吗?


使用您当前的devise,您将始终需要将FieldInfo中字段的名称与string进行比较。 如果将这个解耦合,那么在reflection过程中将该标识符作为属性的一部分用于比较目的。 像这样的东西:

  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); } } 

现在,您可以自由地将Person的_city字段重命名为其他内容,并且您的调用代码仍然可以工作,因为使用reflection的代码尝试使用ReflectionFields枚举值集来标识字段,作为字段上属性集的初始化的一部分。

是的,它可能!

试试这个…

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

这里有两件事

第一,上面的人指出,你得到的stringtypes,而不是人。 所以typeof(Person).GMeMembers()会得到你的成员列表。

第二,更重要的是,看起来你误解了属性的目的。 通常,属性用于标记成员进行特定处理或添加其他信息。 在这里,你使用名称来表示你想要的处理,以及指定参数的属性,这是混合的隐喻,或者什么的。

Abhijeet的回答比较合适,你把这个领域标记为一个城市领域,然后做你喜欢的领域。 我不同意的是,我会使用不同的属性类,而不是枚举。

就像是:

  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; } } } } } 

这将允许您使用MyCity与MyName的不同参数,这将在处理每个参数时更有意义。

我觉得在上面的“你好”的评论中,你碰到了头部。 如果你重命名你的variables,你将不得不改变一个string常量是一个指标,你做错了什么。

 t.GetField("city", BindingFlags.Public | BindingFlags.Instance); 

或者您可以调用GetFields()来获取所有字段

你需要调用Person类的gettypes。 在下面的答案中迭代类的字段

这是不可能的(我认为它实际上只是一些黑客和使用lambdas)。 如果要存储有关Person属性并能够轻松获取该属性的名称,则build议使用System.Collections.Generic命名空间中的Dictionary<TKey, TValue>

而且你总是可以制作包装字典的公共属性。

 public class Person { Dictionary<string, string> attributes = new Dictionary<string, string(); public string City { get { return attributes["city"]; } set { attributes["city"] = value; } } public Person() { City = "New York"; } } 

你可以通过attributes.Keys得到所有属性的列表。

看看这个post,因为它看起来类似于你想要做的:

查找传递给函数的variables名称

(特别是康拉德·鲁道夫的回答)另一种方法可能是将“城市”添加为属性中的一个参数,并在以后出现。

您已经循环了FieldInfo对象的集合。 寻找你的属性,当你find包含你的属性的FieldInfo ,你有你想要的。 然后调用.Name

system.reflection.fieldinfo.attributes