C #: есть ли способ получить доступ к имени текущего поля? - PullRequest
2 голосов
/ 05 апреля 2011

В C # я определяю статическое поле определенного класса.Внутри класса я хочу иметь возможность отображать имя статического поля, примерно так:

public class Unit {
  public string NameOfField { get { return ...; } }
}

public static Unit Hectare = new Unit();

Если я сейчас получу доступ:

Hectare.NameOfField

Я хочу этодля возврата:

Hectare

Я знаю, что есть статическая функция System.Reflection.MethodBase.GetCurrentMethod (), но, насколько я могу судить, нет способа получить имя экземпляра, содержащего этот текущийmethod?

Существует также структура System.RuntimeFieldHandle, но я не смог идентифицировать какой-либо метод GetCurrentFieldHandle ().

Я не уверен, что мне не хватает чего-то очевидного?

Любая помощь в этом очень ценится.

Ответы [ 4 ]

1 голос
/ 05 апреля 2011

Вы не должны рассчитывать на имена переменных в ваших разработках, поскольку они не завершаются во время выполнения.

Лучше инициализировать юнит с именем напрямую:

public class Unit {

  public Unit(string name)
  {
     NameOfField = name;
  }
  public string NameOfField { get; private set;} }
}

public static Unit Hectare = new Unit("Hectare");
0 голосов
/ 06 апреля 2011

Спасибо всем, кто нашел время, чтобы ответить и обсудить мой вопрос.

Просто, чтобы вы знали, я реализовал решение, достаточное для моих нужд.Решение не является общим, и у него есть некоторые подводные камни, но я подумала, что поделюсь им в любом случае, если оно может помочь кому-то еще.

В принципе, это тот класс, который используется при определенииполя выглядят так:

public class Unit : IUnit {
  public NameOfField { get; set; }
  ...
}

Как видите, класс реализует интерфейс IUnit, и я предоставил открытый установщик в свойстве NameOfField.

Статические поля обычно определяются какэто внутри некоторого содержащего класса:

public static Unit Hectare = new Unit();

Мое решение состоит в том, чтобы установить свойство NameOfField посредством отражения, прежде чем поле будет использовано в реализации.Я делаю это с помощью статического конструктора (который, конечно, должен быть вызван до доступа к полям модуля. Я использую Linq для обхода исполняемой сборки для соответствующих полей, и когда я обнаружил эти поля (поля, тип которых реализует интерфейс IUnit)), Я установил свойство NameOfField для каждого из них, используя метод расширения Any:

Assembly.GetExecutingAssembly().GetTypes().
  SelectMany(type => type.GetFields(BindingFlags.Public | BindingFlags.Static)).
  Where(fieldInfo => fieldInfo.FieldType.GetInterfaces().Contains(typeof(IUnit))).
  Any(fieldInfo =>
  {
    ((IUnit)fieldInfo.GetValue(null)).NameOfField= fieldInfo.Name;
    return false;
  });

У этого подхода есть некоторые недостатки:

  • Необходимо вызвать статический конструкторпутем ручного вмешательства до того, как к каким-либо полям модуля можно будет получить доступ
  • Установщик NameOfField является общедоступным. В моем случае это не проблема, но это может быть при применении в других сценариях. (Я предполагаю, что установщик может быть закрытыми призвал к дальнейшим размышлениям, но я не потратил время на дальнейшее изучение этого пути.)
  • ...?

В любом случае, возможно, это решение может помочькто-то еще, чем я.

0 голосов
/ 05 апреля 2011

Вы можете использовать Reflection для получения полей и свойств класса. Как ниже:

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

class Test
{
    public static string MySupperField
    {
        get
        {
            return "Some symbols here";
        }
    }
}

......

Вы можете прочитать имя свойства следующим образом:

public string[] GetClassStaticNames(Type T)
{
    string[] names;

    System.Reflection.PropertyInfo[] props = T.GetProperties(); // This will return only properties not fields! For fields obtaining use T.GetFields();

    names = new string[props.Count()];
    for (int i = 0; i < props.Count(); i++)
    {
        names[i] = props[i].Name;
    }

    return names;
}

Надеюсь, это поможет.

[EDIT]
Возвращаясь к вашему вопросу - Нет, вы не можете получить имя текущей переменной.
То, о чем вы спрашиваете, не может быть сделано из-за природы классов, они являются объектами в памяти, и ссылка на один объект может храниться во многих переменных, и когда вы запрашиваете значение поля или свойства экземпляра, будет фактически выполнена операция с объектом в память не с переменной, которая содержит ссылку на этот объект. Таким образом, получение имени переменной, содержащей ссылку на текущий экземпляр, не имеет смысла

0 голосов
/ 05 апреля 2011

Единственный способ избежать этого - хранить эту информацию в классе:

public static Unit Hectare = new Unit("Hectare");

Когда ваш код компилируется, все имена переменных теряются и заменяются внутренними ссылками. Невозможно снова получить это имя.

...