转换为动态类型变量的通用列表

时间:2011-10-15 09:07:31

标签: c# generics dynamic types casting

我需要更改Capacity类型的动态变量的List<*DynamicType*>属性。 问题是Activator返回object - 如果未指定变量类型而不是正确的List<*DynamicType*>,则转换变量,我能做的最好的事情是将其强制转换为IList:< / p>

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

经过一番搜索,我发现只有一个黑客:

dynamic dynamicList = list;
dynamicList.Capacity = dataRowsCount;

虽然在我的情况下这是可以接受的,但我想知道是否还有另一种方法可以做到这一点。

2 个答案:

答案 0 :(得分:4)

你可以用反射来做到这一点:

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

另一种方法是编写一个通用方法,以静态类型的方式执行所需的所有操作,然后使用反射调用 。这可以是确保您只需要一次反射的便捷方式。

答案 1 :(得分:3)

也许这更简单:

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

哪个应该使用正确的构造函数?

泛型和反思确实是一种痛苦的组合。这里的dynamic hack并不比通过反射(魔术字符串作为文字,与未经验证的属性成员)设置一样丑陋,dynamic内部优化和缓存(每种类型),所以我不会有问题。如果您需要做的不仅仅是一个属性,您还可以使用dynamic翻转一般的方法,以最大限度地减少丑陋:

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

将使用正确的T调用泛型方法。仅仅对于1个成员来说不值得,但它可能对更复杂的场景有用。