使用Activator.CreateInstance进行泛型类型转换
本文关键字:泛型 类型转换 Activator CreateInstance 使用 | 更新日期: 2023-09-27 18:06:45
我有一个接口
public interface ISomething<TValue>
where TValue : IConvertible
{
...
}
然后我也有一些非泛型类与泛型方法:
public class Provider
{
public static void RegisterType<TValue>(ISomething<TValue> instance)
where TValue : IConvertible
{
...
}
}
这似乎都很好,直到我想在我的特定程序集中自动注册所有适用的类型。
public void InitializeApp()
{
foreach(Type t in Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(ISomething<>).IsAssignableFrom(T)))
{
// ERROR
Provider.RegisterType(Activator.CreateInstance(t));
}
}
这段代码导致错误,因为不能从用法中推断参数类型。我应该要么
- 提供显式泛型类型与我的泛型方法
RegisterType
(我不认为我可以这样做,由于我的代码的动态性质)或 - 将
Activator.CreateInstance
的结果转换为适当的类型,因此可以从使用 推断参数类型。
但我也不知道该怎么做?也许还有我不知道的第三种选择
泛型是编译时特性,这意味着在编译时必须知道泛型类型。所以当你只在运行时知道类型时,你的RegisterType
方法不能使用,因为编译器没有办法推断出泛型参数。
这里有几个选项。您可以使用反射来调用正确版本的RegisterType
(如评论中所建议的),或者您可以创建RegisterType
的额外非泛型重载,它接受一个对象并从中计算出执行时类型。
对于前者,它看起来像这样:
public void InitializeApp()
{
foreach(Type t in Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(ISomething<>).IsAssignableFrom(T)))
{
var methodInfo = typeof( Provider ).GetMethod( "RegisterType", BindingFlags.Static );
var registerTypeMethod = methodInfo.MakeGenericMethod( t );
registerTypeMethod.Invoke( null, new[] { Activator.CreateInstance(t) } );
}
}