Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 600
Dmitry Polyanitsa Avatar asked Oct 15 '11 09:10

Dmitry Polyanitsa


People also ask

What are dynamic type variables?

A dynamic type variables are defined using the dynamic keyword. Example: dynamic Variable. dynamic MyDynamicVar = 1; The compiler compiles dynamic types into object types in most cases. However, the actual type of a dynamic type variable would be resolved at run-time.

What are dynamic type variables in c#?

The dynamic type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object . At compile time, an element that is typed as dynamic is assumed to support any operation.

What is the dynamic type of an object?

The dynamic type is the real type of an object that might be accessed via a reference (pointer included) that point to a base type of its real type. class A { }; class B : public A { }; B l; A& k = l; Here k is a reference to an object of type A, but the real type of the referred object, its dynamic type, is B.

What is the difference between dynamic type variables and object type variables?

Dynamic types are similar to object types except that type checking for object type variables takes place at compile time, whereas that for the dynamic type variables takes place at runtime.


2 Answers

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.

like image 54
Jon Skeet Avatar answered Sep 27 '22 22:09

Jon Skeet


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.

like image 44
Marc Gravell Avatar answered Sep 27 '22 20:09

Marc Gravell