У меня есть экземпляр Account
класс. Каждый объект учетной записи имеет владельца, ссылку, и т.д.
Одним путем я могу получить доступ, свойства учетных записей через средства доступа как
account.Reference;
но я хотел бы смочь получить доступ к нему с помощью динамических строковых селекторов как:
account["PropertyName"];
точно так же, как в JavaScript. Таким образом, я имел бы account["Reference"]
который возвратил бы значение, но я также хотел бы смочь присвоить новое значение после этого как:
account["Reference"] = "124ds4EE2s";
Я заметил, что могу использовать
DataBinder.Eval(account,"Reference")
для получения свойства на основе строки но использующий это, я не могу присвоить значение свойству.
Какая-либо идея о том, как я мог сделать это?
Вам нужно использовать Отражение:
PropertyInfo property = typeof(Account).GetProperty("Reference");
property.SetValue(myAccount, "...", null);
Обратите внимание, что это будет очень медленно.
Я согласен с предыдущими сообщениями о том, что вам, вероятно, действительно необходимо использовать свойства. Отражение происходит очень медленно по сравнению с прямым доступом к собственности.
С другой стороны, если вам нужно поддерживать список определяемых пользователем свойств, вы не можете использовать свойства 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;
}
}
}
Если это ваши собственные объекты, вы можете предоставить индексатор для доступа к полям. Я действительно не рекомендую это, но это позволит вам то, что вы хотите.
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
}
}
Обратите внимание, что при этом вы теряете безопасность типов.
Прежде всего, вам следует избегать этого; C # - это язык со строгой типизацией, поэтому воспользуйтесь преимуществами безопасности типов и производительности, которые сопровождают этот аспект.
Если у вас есть законная причина для получения и установки значения свойства динамически (другими словами, когда тип и / или имя свойства не могут быть определены в коде), вам придется использовать отражение.
Наиболее инлайн-вариант выглядит так:
object value = typeof(YourType).GetProperty("PropertyName").GetValue(yourInstance);
...
typeof(YourType).GetProperty("PropertyName").SetValue(yourInstance, "value");
Однако вы можете кэшировать объект PropertyInfo
, чтобы сделать его более читабельным:
System.Reflection.PropertyInfo prop = typeof(YourType).GetProperty("PropertyName");
object value = prop.GetValue(yourInstance);
...
prop.SetValue(yourInstance, "value");
Вы можете попытаться объединить индексатор с отражением ...
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);
}
}