Como você obtém o nome de uma variável como ela foi digitada fisicamente em sua declaração?

Duplicar Possível:
Encontrar o nome da variável passado para uma function em c #

A class abaixo contém a cidade do campo.

Eu preciso determinar dinamicamente o nome do campo como ele é typescript na declaração de class ou seja, eu preciso obter a string “cidade” de uma instância da cidade de object.

Eu tentei fazer isso examinando seu Type em DoSomething (), mas não consigo encontrá-lo ao examinar o conteúdo do Type no depurador.

É possível?

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

Algumas pessoas em suas respostas abaixo me perguntaram por que eu quero fazer isso. Aqui está o porquê.

Na minha situação do mundo real, há um atributo personalizado acima da cidade.

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

Eu preciso desse atributo em outro código. Para obter o atributo, uso a reflection. E no código de reflection eu preciso digitar a string “city”

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

Agora isso não é seguro. Se eu mudei a variável “city” para “workCity” na minha declaração de campo em Person esta linha falharia a menos que eu soubesse atualizar a string

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

Então, eu estou tentando encontrar alguma maneira de passar a string para este código sem digitá-lo fisicamente.

Sim, eu poderia declará-lo como uma constante de string em Person (ou algo assim), mas isso ainda seria digitá-lo duas vezes.

Ufa! Isso foi difícil de explicar !!

obrigado

Obrigado a todos que responderam isso * muito *. Ele me enviou em um novo caminho para entender melhor as expressões lambda. E isso criou uma nova questão.

Talvez você precise disso. Funciona bem.

Eu encontrei isso aqui .

 static void Main(string[] args) { var domain = "matrix"; Check(() => domain); Console.ReadLine(); } static void Check(Expression> 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)); } 

Saída será:

 O nome é: 'domínio'
 O valor é: 'matriz'

Eu sei que esta é uma pergunta antiga, mas eu estava tentando conseguir o mesmo e o google me mandou aqui. Depois de muitas horas, finalmente encontrei um jeito. Espero que alguém ache isso útil.

Na verdade, existem mais maneiras de fazer isso:

 static void Main(string[] args) { GetName(new { var1 }); GetName2(() => var1); GetName3(() => var1); } static string GetName(T item) where T : class { return typeof(T).GetProperties()[0].Name; } static string GetName2(Expression> expr) { return ((MemberExpression)expr.Body).Member.Name; } static string GetName3(Func expr) { return expr.Target.GetType().Module.ResolveField(BitConverter.ToInt32(expr.Method.GetMethodBody().GetILAsByteArray(), 2)).Name; } 

O primeiro é o mais rápido. Os últimos 2 são aproximadamente 20 vezes mais lentos que o primeiro.

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

city , neste caso, é uma instância do tipo string . Quando você chama .GetType() você retorna o tipo de seqüência de caracteres real, que não tem nenhum conhecimento de sua instância particular da cidade.

Eu estou tendo dificuldade em ver porque você não pode simplesmente digitar “city” no código como uma string literal aqui, se é isso que você precisa. Talvez ajudaria se você compartilhasse o valor para o qual deseja usar esse valor e em que circunstâncias chamará sua function DoSomething() .

No momento, meu melhor palpite é que o que você realmente quer fazer é refletir toda a class Person para obter uma lista dos campos dessa 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. } 

Ok, com base na sua edição, eu tenho mais um pouco para você.

Você pode encontrar o nome dos campos que estão decorados com seu atributo em tempo de execução da seguinte forma:

 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 } 

Você também pode usar sinalizadores de binding na primeira chamada GetMembers () para limitá-la a apenas campos, se desejar.

Você mencionou “ou seja, eu preciso pegar a string” city “de uma instância da cidade do object.” Você está procurando obter o nome do campo do valor do campo. Por exemplo: Se houver 2 Person object one com a cidade “New York” e outro com a cidade “London”, você está procurando a function para retornar “city”. É isso que você quer dizer com dynamic?


Com seu design atual, você sempre precisará comparar o nome do campo do FieldInfo com uma string. E se você dissociar isso para que você mantenha o identificador para usar para fins de comparação durante a reflection como parte do atributo. Algo assim:

  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 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.Read(p1); AttributeReader.Read(p2); } } 

Agora você pode renomear livremente o campo _city de Person para outra coisa e seu código de chamada continuará funcionando, pois o código usando reflection está tentando identificar o campo usando o valor de enum ReflectionFields definido como parte da boot do conjunto de atributos no campo.

Sim é possivel !!!

Tente isso …

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

Duas coisas aqui.

Número um, como alguém acima apontou, você está recebendo o tipo por string, não por Person. Então typeof (Person) .GetMembers () irá te dar a lista de membros.

Número dois, e mais importante, parece que você está entendendo mal o propósito dos atributos. Em geral, os atributos são usados ​​para marcar um membro para processamento específico ou para adicionar informações adicionais. Aqui você está usando o nome para indicar o processamento que deseja e o atributo para especificar parâmetros, que é a mistura de metáforas ou algo assim.

A resposta de Abhijeet é mais apropriada, você marca o campo como um campo de cidade e depois faz o que gosta com ele. Onde eu discordo é que eu usaria classs de atributos diferentes, ao invés de uma enumeração.

Algo como:

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

Isso permitiria usar parâmetros diferentes para MyCity vs MyName, o que faria mais sentido no contexto do processamento de cada um.

Eu acho que com o seu comentário ‘yuk’ acima, você bateu o prego na cabeça. O fato de você precisar alterar uma constante de string se renomear sua variável é um indicador de que você está fazendo algo errado.

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

ou você pode chamar GetFields () para obter todos os campos

Você precisa chamar get type na class Person. A iterar os campos da class como na resposta abaixo

Isso não é possível (acho que na verdade é, mas invoca vários hacks e usa lambdas). Se você quiser armazenar atributos sobre uma Person e conseguir obter o nome do atributo facilmente, sugiro usar um Dictionary do namespace System.Collections.Generic .

E você sempre pode criar propriedades públicas que envolvam o dictionary.

 public class Person { Dictionary attributes = new Dictionary 

E você pode obter uma lista de todos os atributos com attributes.Keys .

Dê uma olhada nesta postagem, pois ela é semelhante ao que você está tentando fazer:

Encontrando o nome da variável passado para uma function

(especialmente a resposta de Konrad Rudolph) Outra abordagem poderia ser apenas adicionar “cidade” como um dos parâmetros no atributo e pescar mais tarde.

Você já está circulando pela coleção de objects FieldInfo . Procure por seu atributo e quando você encontrar o FieldInfo que contém seu atributo, você tem o que você quer. Em seguida, chame .Name nele.

system.reflection.fieldinfo.attributes