我正在尝试实例化带有先前在字符串变量中定义的类的列表。我什至不知道是否可能,但我认为是这样。
string class1 = "class1";
string class2 = "class2";
bool condition = getCondition();
string classToInstanciate = "";
if(condition) classToInstanciate = class1;
else classToInstanciate = class2;
List<classToInstanciate> dtos = Parse(source).ToList();
这里是pb,显然这是行不通的,但是我想用需要使用的类来实例化此列表。
答案 0 :(得分:1)
C#中的类型的泛型类型参数不能松散地表达-它们必须非常明确,因此,当您要混合泛型和反射时,它总是有些混乱。
这里的第一项工作是获得Type
而不是string
。如果您可以在整个过程中使用typeof
,那就简单得多了,即
Type classToInstanciate;
if (condition) classToInstanciate = typeof(Class1);
else classToInstanciate = typeof(Class2);
否则,您将不得不使用Type.GetType(fullyQualifiedName)
或someAssembly.GetType(fullName)
等,这样会很混乱。
接下来,您需要从反射(Type
)切换到泛型(<T>
)。有多种方法可以执行此操作,但是最简单的方法通常是:MakeGenericMethod
。例如:
class SomeType {
// can make this non-public, but then you need to specify BindingFlags
// in the GetMethod call
public static List<T> DoTheThing<T>(whateverArgs) {
List<T> dtos = Parse<T>(source).ToList(); // whatever...
///
return dtos;
}
...
private static IList CallTheThing(Type type, whateverArgs)
{
return (IList) typeof(SomeType).GetMethod(nameof(DoTheThing))
.MakeGenericMethod(type).Invoke(null, whateverArgs);
// "null" above is the target instance; in this case static, hence null
}
// ...
}
然后您可以使用:
IList list = CallTheThing(classToInstanciate, otherArgs);
调用站点上的list
仅(且必须是)仅称为非通用IList
API。如果您需要使用通用方面(List<T>
等),则可以在DoTheThing<T>
内部进行。即使本身仅被称为List<T>
,列表本身仍然是T
(属于正确的IList
)-因此您不能向其中添加不正确的项,等等