Search code examples
c#reflectioncollectionssystem.reflection

Modify collection items using reflection?


I'd like to use reflection to find a collection by name (MyAssembly.Constants.MyCollection), check its items (List<string>), and add an item if it doesn't already exist. So far I'm able to find the collection and see its items, but need help adding the missing value to the real collection. Here's what I have so far:

var assembly = Assembly.Load("MyAssembly");
var constants = assembly.GetType("MyAssembly.Constants");
var myCollection = constants.GetField("MyCollection").GetValue(null) as List<string>;

if (!myCollection.Contains("some_value"))
{
     //Add the missing item to MyAssembly.Constants.MyCollection
}

Solution

  • readonly only applies to the field and means that you cannot assign it another (or the same) collection instance or null. It does not mean that the collection itself is a read-only collection.

    Since you have a variable myCollection typed as List<string>, you do not need Reflection. Just write

    myCollection.Add("some value"); // allowed.
    

    Note that a List<T> is a class and therefore a reference type. I.e., the variable myCollection contains a reference to the real collection. myCollection.Add("some value"); adds the new value to the real collection (MyAssembly.Constants.MyCollection)!

    But something like Constants.MyCollection = null; is not allowed because of the readonly keyword.

    Example:

    static readonly List<string> myCollection = new List<string>();
    static ReadOnlyCollection<string> roc = new ReadOnlyCollection<string>(myCollection);
    

    readonly fields or properties can be initialized with an initializer expression or in a constructor. Given the declarations above:

    myCollection.Add("text"); // OK, collection not readonly.
    myCollection = new List<string>(); // NOT POSSIBLE, field readonly.
    
    roc.Add("text"); // NOT POSSIBLE, readonly collection has no Add method.
    roc = new ReadOnlyCollection<string>(new[] { "a", "b" }); // OK, roc field not readonly.
    

    static does not mean that the field or collection cannot be changed. It means that the field is not an instance field that must be referenced through a class instance (an object), rather, it belongs to the class and can be accessed through the class name.

    Example:

    class MyClass
    {
        public static int staticField;
        public        int instanceField;
    }
    

    Given the declaration above:

    var obj = new MyClass();
    var x = obj.instanceField;    // OK
    var y = MyClass.staticField;  // OK
    
    var z = MyClass.instanceField; // DOES NOT COMPILE!
    // CS0120: An object reference is required for the nonstatic field, method, or property 
    //         'MyClass.instanceField'
    
    var t = obj.staticField;       // DOES NOT COMPILE!
    // CS0176: Static member 'MyClass.staticField' cannot be accessed with an instance
    //         reference; qualify it with a type name instead