2010-05-25 3 views
28

У меня есть экземпляр класса Account. Каждый объект учетной записи есть владелец, ссылка и т.д.Доступ к объекту как строка и установка его значения

Один из способов я могу получить доступ к счетам свойства через аксессор как

account.Reference; 

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

account["PropertyName"]; 

как и в JavaScript. Так что я бы account["Reference"], который будет возвращать значение, но я также хотел бы иметь возможность присвоить новое значение после того, как:

account["Reference"] = "124ds4EE2s"; 

Я заметил, что я могу использовать

DataBinder.Eval(account,"Reference") 

в получить свойство на основе строки, но используя это, я не могу присвоить значение этому свойству.

Любая идея о том, как я могу это сделать?

+1

Вы имеете в виду «C#», не так ли, а не «csharp»? –

+2

C# не является языком сценариев; обычно при изучении нового языка; вам нужно будет изучить новые идиомы и соглашения, которые согласуются с ним. – Pierreten

ответ

40

Прежде всего, вам следует избегать использования этого; C# - строго типизированный язык, поэтому используйте преимущества безопасности и производительности типа, которые сопровождают этот аспект.

Если у вас есть законная причина для получения и установки значения свойства динамически (другими словами, когда тип и/или имя свойства не могут быть определены в коде), вам придется использование отражение.

Наиболее рядный ищет путь будет таким:

object value = typeof(YourType).GetProperty("PropertyName").GetValue(yourInstance, null); 
... 
typeof(YourType).GetProperty("PropertyName").SetValue(yourInstance, "value", null); 

Однако, вы можете кэшировать PropertyInfo объект, чтобы сделать его более удобным для чтения:

System.Reflection.PropertyInfo prop = typeof(YourType).GetProperty("PropertyName"); 

object value = prop.GetValue(yourInstance, null); 
... 
prop.SetValue(yourInstance, "value", null); 
+62

Кто-то сказал мне, что C# слишком сильно напечатан. После небольшого размышления я решил, что это было не так уж плохо. – deed02392

+2

вы можете сэкономить много кода (и меньше ошибок кода = меньше), используя это для сохранения. Используйте его, как ruby, и сделайте таблицу db соответствующей вашим свойствам и сосредоточьтесь на алгоритмах, а не на бесконечном наборе текста (как сильные, так и на клавиатуре). –

1

Вы должны использовать Reflection:

PropertyInfo property = typeof(Account).GetProperty("Reference"); 

property.SetValue(myAccount, "...", null); 

Обратите внимание, что это будет очень медленно.

3

Если это ваши собственные объекты, вы можете предоставить индекс для доступа к полям. Я не рекомендую это, но это позволит вам что угодно.

public object this[string propertyName] 
{ 
    get 
    { 
     if(propertyName == "Reference") 
      return this.Reference; 
     else 
      return null; 
    } 
    set 
    { 
     if(propertyName == "Reference") 
      this.Reference = value; 
     else 
      // do error case here    
    } 
} 

Обратите внимание, что при этом вы теряете безопасность типа.

1

Я согласен с предыдущими плакатами, что вы, вероятно, должны использовать свойства. Отражение происходит очень медленно по сравнению с прямым доступом к свойствам.

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

public class Account 
{ 
    Dictionary<string, object> properties; 
    public object this[string propertyName] 
    { 
     get 
     { 
      if (properties.ContainsKey[propertyName]) 
       return properties[propertyName]; 
      else 
       return null; 
     } 
     set 
     { 
      properties[propertyName] = value; 
     } 
    } 
} 
23

Вы можете попробовать сочетание индексации с отражением ...

public object this[string propertyName] 
{ 
    get 
    { 
     PropertyInfo property = GetType().GetProperty(propertyName); 
     return property.GetValue(this, null); 
    } 
    set 
    { 
     PropertyInfo property = GetType().GetProperty(propertyName); 
     property.SetValue(this,value, null); 
    } 
} 
+0

Хорошая работа. Это мне очень помогло – sudhAnsu63

+2

+1 Работает и для меня. Обратите внимание, что вам нужно обработать свойство, возможно, равное нулю. –

1

лично я предпочитаю работать с методами расширения, так вот мой код:

public static class ReflectionExtensions 
{ 
    public static void SetPropertyValue(this object Target, 
     string PropertyName, 
     object NewValue) 
    { 
     if (Target == null) return; //or throw exception 

     System.Reflection.PropertyInfo prop = Target.GetType().GetProperty(PropertyName); 

     if (prop == null) return; //or throw exception 

     object value = prop.GetValue(Target, null); 

     prop.SetValue(Target, NewValue, null); 
    } 
} 
1

Если вы используете .NET 4 вы можете использовать динамический ключевое слово в настоящее время.

dynamic foo = account; 
foo.Reference = "124ds4EE2s"; 
3

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

public object this[string propertyName] 
{ 
    get 
    { 
     PropertyInfo property = GetType().GetProperty(propertyName); 
     return property.GetValue(this, null); 
    } 
    set 
    { 
     PropertyInfo property = GetType().GetProperty(propertyName); 
     Type propType = property.PropertyType; 
     if (value == null) 
     { 
      if (propType.IsValueType && Nullable.GetUnderlyingType(propType) == null) 
      { 
       throw new InvalidCastException(); 
      } 
      else 
      { 
       property.SetValue(this, null, null); 
      } 
     } 
     else if (value.GetType() == propType) 
     { 
      property.SetValue(this, value, null); 
     } 
     else 
     { 
      TypeConverter typeConverter = TypeDescriptor.GetConverter(propType); 
      object propValue = typeConverter.ConvertFromString(value.ToString()); 
      property.SetValue(this, propValue, null); 
     } 
    } 
} 

Функция SetValue() выдаст ошибку, если преобразование не работает.

 Смежные вопросы

  • Нет связанных вопросов^_^