Доступ к переменной экземпляра по имени (строке), как это делают динамические языки, в C#

у меня есть такой код С#:

string fieldName = ...
string value = ...

if (fieldName == "a") a = value;
if (fieldName == "b") b = value;
if (fieldName == "c") c = value;
if (fieldName == "d") d = value;
...

Я хочу что-то вроде этого:

string fieldName = ...
string value = ...

SetMyInstanceVariable(fieldName, value);
...

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


person Chris    schedule 19.01.2010    source источник
comment
Что произойдет, если fieldName будет SetMyInstanceVariable?   -  person YOU    schedule 19.01.2010


Ответы (3)


Dictionary<string, string> - самый простой подход:

public class Bag {
  var props = new Dictionary<string, string>();

  // ...

  public string this[string key] {
    get { return props[key]; }
    set { props[key] = value; }
  }
}

Подход с отражением значительно сложнее, но все же выполним:

public class Fruit {
  private int calories = 0;
}

// ...

var f = new Fruit();
Type t = typeof(Fruit);

// Bind to a field named "calories" on the Fruit type.
FieldInfo fi = t.GetField("calories",
  BindingFlags.NonPublic | BindingFlags.Instance);

// Get the value of a field called "calories" on this object.
Console.WriteLine("Field value is: {0}", fi.GetValue(f));

// Set calories to 100. (Warning! Will cause runtime errors if types
// are incompatible -- try using "100" instead of the integer 100, for example.)
fi.SetValue(f, 100);

// Show modified value.
Console.WriteLine("Field value is: {0}", fi.GetValue(f));
person John Feminella    schedule 19.01.2010

Если они являются свойствами в вашем классе, вы можете использовать:

this.GetType().GetProperty(fieldName).SetValue(this, value, null);

Поле в классе

this.GetType().GetField(fieldName).SetValue(this, value, null);

Возможно, вам потребуется изменить флаги привязки в зависимости от общедоступного/закрытого статуса полей.

Если они просто локальные переменные для функции, как вы описали, однако я считаю, что вам может не повезти.

Гораздо предпочтительнее использовать тип данных, предназначенный для использования таким образом, как словарь, и, возможно, вам следует подумать о замене существующих переменных свойствами, которые ссылаются на словарь. Например: string a { get { return myDictionary["a"]; } }. Это может позволить вам сохранить обратную совместимость, не прибегая к отражению, которое действительно должно быть последним средством.

person fyjham    schedule 19.01.2010

Как насчет хранения всего этого в Dictionary<string, string>?

person shahkalpeshp    schedule 19.01.2010
comment
Сейчас немного поздно, это зрелая кодовая база. Надо было сделать это с самого начала! Спасибо за ответ. - person Chris; 19.01.2010