Search code examples
c#arraysdynamiclate-bindingactivator

RuntimeBinderException when trying to instantiate an array of a dynamic type (late-binding)


I am trying to use Activator.CreateInstance() to instantiate an array that has fields of a dynamic type (I get the type that I must use for array fields during the runtime as Type arrayType = arrayFieldType.MakeArrayType()).

singleSet.ZaznamyObjektu = Activator.CreateInstance(arrayType, new object[] { rowCount });

(rowCount is an integer.) I have chosen this approach according to How do I create a C# array using Reflection and only type info? but it keeps giving me RuntimeBinderException:

Cannot implicitly convert type 'object' to 'PodperneZarizeniTypeZaznamObjektu[]'. An explicit conversion exists (are you missing a cast?)

But I do not know how to make cast or conversion when I cannot use the exact name of the type. I have also tried to use Array.CreateInstance() but it was giving me similar exception:

Cannot implicitly convert type 'System.Array' to 'PodperneZarizeniTypeZaznamObjektu[]'. An explicit conversion exists (are you missing a cast?)


Solution

  • but it keeps giving me RuntimeBinderException:

    Cannot implicitly convert type 'object' to 'PodperneZarizeniTypeZaznamObjektu[]'. An explicit conversion exists (are you missing a cast?)

    That doesn't look like a runtime exception at all. That looks like a compile time error.

    In comments you are saying that the type of singleSet.ZaznamyObjektu is PodperneZarizeniTypeZaznamObjektu[]. Activator.CreateInstance returns an object, bear in mind that CreateInstance is potentialy valid for any type. You can't assign an object to an array typed property.

    Your problem seems to be that you are simply missing a cast:

    singleSet.ZaznamyObjektu = (PodperneZarizeniTypeZaznamObjektu[])Activator.CreateInstance(arrayType, new object[] { rowCount });
    

    Now, do note, that this will fail miserably in the following scenarios:

    1. arrayField is a reference type and there is no valid identity preserving reference conversion between an arrayField and a PodperneZarizeniTypeZaznamObjektu.

      (Mammal[])tigers; //valid
      (Insect[])tigers; //evidently not.
      
    2. arrayField is a value type and its type is not PodperneZarizeniTypeZaznamObjektu's type. Even if there is an implicit / explicit cast operator, it will fail; array type variance is not permitted with value types.

      (long[])(ints); //not valid even though an implicit cast
                      //from int to long exists