Как получить имя свойства из свойства В C# (2.0)
Я знаю, что у меня может быть атрибут, но это больше работы, чем я хочу... и недостаточно общий.
Я хочу сделать что-то вроде
class Whotsit
{
private string testProp = "thingy";
public string TestProp
{
get { return testProp; }
set { testProp = value; }
}
}
...
Whotsit whotsit = new Whotsit();
string value = GetName(whotsit.TestProp); //precise syntax up for grabs..
где я ожидал бы, что значение будет равно "TestProp"
но я не могу для жизни меня найти правильные методы отражения, чтобы написать метод GetName...
EDIT: почему я хочу это сделать? У меня есть класс для хранения настроек, считанных из таблицы "имя", "значение". Это заполняется обобщенным метод, основанный на рефлексии. Я бы хотел написать обратное...
/// <summary>
/// Populates an object from a datatable where the rows have columns called NameField and ValueField.
/// If the property with the 'name' exists, and is not read-only, it is populated from the
/// valueField. Any other columns in the dataTable are ignored. If there is no property called
/// nameField it is ignored. Any properties of the object not found in the data table retain their
/// original values.
/// </summary>
/// <typeparam name="T">Type of the object to be populated.</typeparam>
/// <param name="toBePopulated">The object to be populated</param>
/// <param name="dataTable">'name, 'value' Data table to populate the object from.</param>
/// <param name="nameField">Field name of the 'name' field'.</param>
/// <param name="valueField">Field name of the 'value' field.</param>
/// <param name="options">Setting to control conversions - e.g. nulls as empty strings.</param>
public static void PopulateFromNameValueDataTable<T>
(T toBePopulated, System.Data.DataTable dataTable, string nameField, string valueField, PopulateOptions options)
{
Type type = typeof(T);
bool nullStringsAsEmptyString = options == PopulateOptions.NullStringsAsEmptyString;
foreach (DataRow dataRow in dataTable.Rows)
{
string name = dataRow[nameField].ToString();
System.Reflection.PropertyInfo property = type.GetProperty(name);
object value = dataRow[valueField];
if (property != null)
{
Type propertyType = property.PropertyType;
if (nullStringsAsEmptyString && (propertyType == typeof(String)))
{
value = TypeHelper.EmptyStringIfNull(value);
}
else
{
value = TypeHelper.DefaultIfNull(value, propertyType);
}
property.SetValue(toBePopulated, System.Convert.ChangeType(value, propertyType), null);
}
}
}
дальнейшее редактирование: я просто в коде, есть экземпляр Whotsit, и я хочу получить текстовую строку Свойства 'TestProp'. Это кажется странным, я знаю, я могу просто использовать буквальный "TestProp" - или в случае моего класса для функции datatable я был бы в цикле foreach PropertyInfos. Мне просто любопытно...
исходный код строковые константы, которые я нашел неуклюжий.
7 ответов
нет, здесь нечего делать. Выражение whotsit.TestProp
будет оценивать собственность. Вам нужен мифический оператор" infoof":
// I wish...
MemberInfo member = infoof(whotsit.TestProp);
как есть, вы можете использовать только отражение, чтобы получить свойство по имени - не из кода. (Или получить все свойства, конечно. Это все еще не помогает вам с вашим образцом.)
один из вариантов-использовать дерево выражений:
Expression<Func<string>> = () => whotsit.TestProp;
затем изучите дерево выражений, чтобы получить свойство.
Если ничего не помогает, возможно, вы могли бы рассказать нам больше о том, почему вы хотите эту функциональность?
это возможно (без отражения), но только с последним C# 3.0
быстрый и очень грязный
class Program
{
static void Main()
{
string propertyName = GetName(() => AppDomain.CurrentDomain);
Console.WriteLine(propertyName); // prints "CurrentDomain"
Console.ReadLine();
}
public static string GetName(Expression<Func<object>> property)
{
return property.Body.ToString().Split('.').Last();
}
}
обновление: Я только что понял, что Джон Скит (кто-нибудь удивлен? :) уже рассмотрел эту возможность, но я сохраню свой ответ здесь, на случай, если кто-то заинтересован в каком-то примере для начала.
Я не думаю, что это возможно, единственный способ сделать это-перебрать свойства:
class TestClass
{
private string _field;
public string MyProperty
{
get { return _field; }
}
}
class Program
{
static void Main(string[] args)
{
TestClass test = new TestClass();
PropertyInfo[] info = test.GetType().GetProperties();
foreach(PropertyInfo i in info)
Console.WriteLine(i.Name);
Console.Read();
}
}
Kpollack, вы сказали в предыдущем комментарии:
что все равно не даст мне возможности получить имя свойства из его экземпляра.
Это заставляет меня поверить, что у вас как-то есть ссылка на свойство. Как вы получили эту ссылку? Каков его тип? Не могли бы вы предоставить образец кода? Если это объект PropertyInfo, у вас уже есть то, что вам нужно; поскольку это не так, мы имеем дело с чем-то другим, и Мне было бы очень интересно посмотреть, что это такое, что вы do должны работать.
P.S. Простите, что я кажусь тупым: еще рано, я не выпил достаточно кофе, и у меня нет моей IDE передо мной. :-/
то, что вы пытаетесь сделать, невозможно. Используя отражение, вы можете:
- получить свойство, поле или сведения о методе из его имени строки.
- получить список всех свойств, полей или методов для данного типа.
ваш метод GetName при вызове передается строка. GetMethod будет знать о строке, но не сохраняет метаданные исходного свойства.
из интереса, почему вы пытаетесь это сделать?
FYI, я попытался сериализовать его, чтобы увидеть, случайно ли, что содержит имя свойства, но не повезло.
Не работает код ниже:
Whotsit w = new Whotsit();
XmlSerializer xs = new XmlSerializer(w.TestProp.GetType());
TextWriter sw = new StreamWriter(@"c:\TestProp.xml");
xs.Serialize(sw, w.TestProp);
sw.Close();
на GetProperties на тип класса даст вам список свойств этого типа.
Type t = whotsit.GetType();
PropertyInfo[] pis = t.GetProperties();