简体   繁体   中英

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
  2. cast results from Activator.CreateInstance to appropriate type so argument type could be inferred from usage

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM