在字符串中定义的我的班级名称的实例列表

时间:2019-03-27 10:44:33

标签: c# string list

我正在尝试实例化带有先前在字符串变量中定义的类的列表。我什至不知道是否可能,但我认为是这样。

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,显然这是行不通的,但是我想用需要使用的类来实例化此列表。

1 个答案:

答案 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)-因此您不能向其中添加不正确的项,等等