Как я могу получить значение строкового свойства через Reflection?

Asked
Viewd69844

22
 public class Foo
{
   public string Bar {get; set;}
}
 

Как получить значение строкового свойства Bar через отражение? Следующий код вызовет исключение, если тип PropertyInfo - System.String

 Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

foreach(var property in f.GetType().GetProperties())
{
 object o = property.GetValue(f,null); //throws exception TargetParameterCountException for String type
}
 

Похоже, моя проблема в том, что это свойство относится к типу индексатора с System.String.

Кроме того, как узнать, является ли свойство индексатором?

  • Ага. Отладчик сообщает, что основным типом является строка, но я подозреваю, что происходит что-то еще.

    Alan12 июня 2009, 17:45
  • похоже, что вы публикуете недостаточно контекстного кода?

    Firoso12 июня 2009, 17:42
  • здесь отлично работает… что-то еще происходит?

    womp12 июня 2009, 17:41

9 ответов

49

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

 Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

var barProperty = f.GetType().GetProperty("Bar");
string s = barProperty.GetValue(f,null) as string;
 

Относительно следующего вопроса: Индексаторы всегда будут называться Item и иметь аргументы в получателе. Итак

 Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

var barProperty = f.GetType().GetProperty("Item");
if (barProperty.GetGetMethod().GetParameters().Length>0)
{
    object value = barProperty.GetValue(f,new []{1/* indexer value(s)*/});
}
 
  • Я совершенно не знал об атрибуте IndexerName! Спасибо. Вы можете найти дополнительную информацию здесь: http://bartdesmet.net/blogs/bart/archive/2006/09/09/4408.aspx Спасибо Jb Evain.

    Jake03 февраля 2010, 07:09
  • Неточно. Item - это имя по умолчанию для индексаторов, но любой может использовать IndererNameAttribute в свойстве индексатора, чтобы изменить это. Вы должны искать атрибут DefaultMemberAttribute в типе, чтобы получить фактическое имя индексатора.

    Jb Evain01 февраля 2010, 16:01
4
 var val = f.GetType().GetProperty("Bar").GetValue(f, null);
 
3
 Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

foreach(var property in f.GetType().GetProperties())
{
    if(property.Name != "Bar")
    {
         continue;
    }
    object o = property.GetValue(f,null); //throws exception TargetParameterCountException for String type
}
  А вот продолжение: 
 class Test
{
    public class Foo
    {
        Dictionary<string, int> data =new Dictionary<string,int>();
        public int this[string index]
        {
            get { return data[index]; }
            set { data[index] = value; }
        }

        public Foo()
        {
            data["a"] = 1;
            data["b"] = 2;
        }
    }

    public Test()
    {
        var foo = new Foo();
        var property = foo.GetType().GetProperty("Item");
        var value = (int)property.GetValue(foo, new object[] { "a" });
        int i = 0;
    }
}
 
  • Основываясь на других комментариях, вам нужно будет изменить значение null при получении на правильные значения индексатора.

    Jake Pearson12 июня 2009, 17:43
4
 Foo f = new Foo();
f.Bar = "x";

string value = (string)f.GetType().GetProperty("Bar").GetValue(f, null);
 
2
 PropertyInfo propInfo = f.GetType().GetProperty("Bar");
object[] obRetVal = new Object[0];
string bar = propInfo.GetValue(f,obRetVal) as string;
 
  • за что именно проголосовали против? этот код работает должным образом.

    Stan R.01 февраля 2010, 15:56
5

Мне не удалось воспроизвести проблему. Вы уверены, что не пытаетесь сделать это на каком-то объекте со свойствами индексатора? В этом случае ошибка, с которой вы столкнулись, будет выдана при обработке свойства Item. Также вы можете сделать это:

 
public static T GetPropertyValue<T>(object o, string propertyName)
{
      return (T)o.GetType().GetProperty(propertyName).GetValue(o, null);
}

...somewhere else in your code...
GetPropertyValue<string>(f, "Bar");