C# 强制转换为动态类型的通用变量列表

C# 强制转换为动态类型的通用变量列表,c#,generics,dynamic,types,casting,C#,Generics,Dynamic,Types,Casting,我需要更改类型为List的动态变量的Capacity属性。 问题是如果没有指定变量类型而不是正确的列表,则Activator返回object-casted变量,我能做的最好的方法是将其强制转换到IList: DynamicTypeBuilder builder = new DynamicTypeBuilder() { ... }; Type dataType = builder.GenerateType(...); Type listDataType = typeof(List<>)

我需要更改类型为
List
的动态变量的
Capacity
属性。 问题是如果没有指定变量类型而不是正确的
列表
,则
Activator
返回
object
-casted变量,我能做的最好的方法是将其强制转换到
IList

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

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

您可以通过反射来实现:

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

另一种方法是编写一个泛型方法,它以静态类型的方式完成您想要的一切,并使用反射来调用它。这是一种简便的方法,可以确保您只需要一个反射。

也许这更简单:

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);
void Evil(列表,整数容量){
列表。容量=容量;
//做其他事情
}
...
动态列表=Activator.CreateInstance(listDataType);
邪恶(列表,数据行);

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

忘记了那个构造函数。因为我只需要设置那个属性,所以用这种方法做会更简单。我也喜欢你的建议,使用泛型方法“强制转换”IList对象,非常好。顺便说一句,虽然我可能做了一些错误,但在我的例子中,将
Activator.CreateInstance()
的结果赋给
generic
变量是行不通的,因为
list.Add(*动态创建的数据类型对象*)
会导致异常,通过将
list
预转换为
IList
可以工作。@d请尝试确定,然后转换为
IList
。我在示例中没有这样做,只是因为我演示了示例中执行操作的最小值,并且示例没有
Add(…)
Nice,出于某种原因没有考虑反射。当我再次处理动态\泛型时,我会记住这一点。
void Evil<T>(List<T> list, int capacity) {
    list.Capacity = capacity;
    // do other stuff
}
...
dynamic list = Activator.CreateInstance(listDataType);
Evil(list, dataRowsCount);