Dmitry Polyanitsa
Dmitry Polyanitsa

Reputation: 1093

Casting to a generic list of variables of dynamic type

I need to change the Capacity property of the dynamic variable of type List<*DynamicType*>. The problem is that Activator returns object-casted variable if variable type is not specified instead of proper List<*DynamicType*> and the best I can do is to cast it to IList:

DynamicTypeBuilder builder = new DynamicTypeBuilder() { ... };
Type dataType = builder.GenerateType(...);
Type listDataType = typeof(List<>).MakeGenericType(dataType);
IList list = (IList)Activator.CreateInstance(listDataType);

After some searching I found only one hack:

dynamic dynamicList = list;
dynamicList.Capacity = dataRowsCount;

Though this would be acceptable in my case I wonder if there is another way to do this.

Upvotes: 5

Views: 2285

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1064144

Perhaps this is simpler:

object list = Activator.CreateInstance(listDataType,
    new object[]{dataRowsCount});

Which should use the correct constructor?

Generics and reflection are indeed a pain in combination. The dynamic hack here is no uglier than setting it via reflection (a magic string as a literal, vs an unverified property member), and dynamic is internally optimised and cached (per-type), so I wouldn't have a problem with it. If you need to do more than just one property, you can also use dynamic to flip into a generic method, to minimise the ugly:

void Evil<T>(List<T> list, int capacity) {
    list.Capacity = capacity;
    // do other stuff
}
...
dynamic list = Activator.CreateInstance(listDataType);
Evil(list, dataRowsCount);

Which will invoke the generic method with the correct T. Not worth it just for 1 member, but it might be useful for more complex scenarios.

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1503669

You can do it with reflection:

var capacityProperty = listDataType.GetProperty("Capacity");
capacityProperty.SetValue(list, dataRowsCount, null);

An alternative is to write a generic method which does everything you want in a statically typed way, and call that with reflection instead. That can be a handy way of making sure you only need one piece of reflection.

Upvotes: 4

Related Questions