简体   繁体   English

使用Activator.CreateInstance进行通用类型转换

[英]Generic type casting using Activator.CreateInstance

I have an interface 我有一个界面

public interface ISomething<TValue>
    where TValue : IConvertible
{
    ...
}

Then I also have some non-generic class with a generic method: 然后,我还有一些具有泛型方法的非泛型类:

public class Provider
{
    public static void RegisterType<TValue>(ISomething<TValue> instance)
        where TValue : IConvertible
    {
        ...
    }
}

This seems all fine until I want to automatically register all applicable types in my particular assembly. 直到我要在我的特定程序集中自动注册所有适用的类型之前,这似乎还不错。

public void InitializeApp()
{
    foreach(Type t in Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(ISomething<>).IsAssignableFrom(T)))
    {
        // ERROR
        Provider.RegisterType(Activator.CreateInstance(t));
    }
}

This code results in error as argument type can't be inferred from usage. 此代码导致错误,因为无法从用法中推断出参数类型。 I should either 我要么

  1. provide explicit generic type with my generic method RegisterType (I don't think I can do this due to dynamic nature of my code) or 使用我的通用方法RegisterType提供显式的通用类型(由于代码的动态性质,我不认为可以做到这一点)或
  2. cast results from Activator.CreateInstance to appropriate type so argument type could be inferred from usage 将结果从Activator.CreateInstance为适当的类型,以便可以从用法中推断出参数类型

But I don't know how to do either? 但是我也不知道该怎么办? Maybe there's a third option I'm not aware of. 也许还有我不知道的第三种选择。

Generics are a compile-time feature, meaning that the generic types must be known at compile time. 泛型是编译时的功能,这意味着必须在编译时知道泛型类型。 So your RegisterType method can't be used when you only know the type at runtime, since there's no way for the compiler to deduce the generic parameter. 因此,当您仅在运行时知道类型时,就不能使用RegisterType方法,因为编译器无法推断出通用参数。

You have a couple options here. 您在这里有几个选择。 You can either use reflection to call the correct version of RegisterType (as suggested in the comments), or you can create an additional non-generic overload of RegisterType that accepts an object and figures out the execution-time type from that. 您可以使用反射来调用正确版本的RegisterType (如注释中所建议),或者可以创建RegisterType的其他非泛型重载,该重载接受对象并从中找出执行时类型。

For the former, that would look something like this: 对于前者,它看起来像这样:

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) } );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Activator.CreateInstance后转换为正确的类型 - Casting to correct type after using Activator.CreateInstance 具有通用存储库的Activator.CreateInstance - Activator.CreateInstance with a generic repository 具有动态类型的Activator.CreateInstance - Activator.CreateInstance with dynamic Type InvalidCastException:带有常规继承类型的Activator.CreateInstance - InvalidCastException: Activator.CreateInstance w/ Generic Inheriting Type 无法使用通用方法类型 <T> 直接在Activator.CreateInstance中 - Unable to use generic method type <T> directly in Activator.CreateInstance Activator.CreateInstance和Activator.CreateInstance之间的区别<Type> - difference between Activator.CreateInstance and Activator.CreateInstance<Type> 如何使用Activator.CreateInstance实例化泛型类型作为using块的一部分? - How can I use Activator.CreateInstance to instantiate a generic type as part of a using block? 在泛型类中使用Activator.CreateInstance结合方法上的“ new”修饰符 - Using Activator.CreateInstance in generic class combined with “new” modifier on method 结合使用Activator.CreateInstance()和属性 - Using Activator.CreateInstance() with properties 是否可以使用Activator.CreateInstance()使用参数构造函数创建泛型工厂? - Is it possible to create a generic factory with constructor with parameters using Activator.CreateInstance()?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM