我有一个界面
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
的结果转换为适当的类型,因此可以从用法但我不知道怎么做?也许还有我不知道的第三种选择。
答案 0 :(得分:2)
泛型是一个编译时功能,这意味着必须在编译时知道泛型类型。因此,当您只知道运行时的类型时,不能使用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) } );
}
}