Accessing an instance variable by name (string), kinda like dynamic languages do, in C#

╄→尐↘猪︶ㄣ 提交于 2021-02-04 06:51:50

问题


i've got some C# code like this:

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

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

I want something like this:

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

SetMyInstanceVariable(fieldName, value);
...

Is there a simple way to do it? I know that given a class's name in a string, you can instantiate it with System.Activator, and this is kindof similar so i was hoping....


回答1:


A Dictionary<string, string> is the easiest approach:

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

  // ...

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

The reflection approach is considerably more complex but still doable:

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));



回答2:


If they are properties in your class you can use:

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

A field in the class

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

You may need to alter binding flags based on the public/private status of the fields.

If they're just local variables to a function like you've described however I believe you may be out of luck.

It's by far preferable to use a datatype designed to be used in this way like a Dictionary, and perhaps you should consider replacing the existing variables with Properties that reference the dictionary. EG: string a { get { return myDictionary["a"]; } }. This may let you keep backwards compatibility without resorting to reflection, which really should be a last resort.




回答3:


How about storing it all in a Dictionary<string, string>?



来源:https://stackoverflow.com/questions/2091190/accessing-an-instance-variable-by-name-string-kinda-like-dynamic-languages-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!