Аргументы обобщенного типа для типа в 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
.