Casting generic to interface type - Unable to cast object of type 'System.RuntimeType' to type

10,987

Solution 1

You cannot cast (IRepository) type with type is Type class,

you can use Activator.CreateInstance to create object CustomerRepository, you also don't need to use Select, instead, use ToDictionary directly, the code below:

var myRepositories = Assembly.GetAssembly(typeof(Repository<>))
       .GetTypes()
       .Where(x => x.BaseType != null && 
                   x.BaseType.GetGenericArguments().FirstOrDefault() != null)

       .ToDictionary(x => x.BaseType.GetGenericArguments().FirstOrDefault(), 
                            x => Activator.CreateInstance(x) as IRepository );

Solution 2

If x is a System.Type object, like if x is typeof(Repository<>), you can't just cast it like that. The Type is not an instantiation.

If x had no "free" type parameters, that is if x where non-generic or closed generic, then (IRepository)Activator.CreateInstance(x) might create you an object of type x. But I'm not sure that's what you need. Will there be a parameterless instance constructor?

Share:
10,987

Related videos on Youtube

Alex
Author by

Alex

I'm a .net developer from Camberley, Surrey. Strong interest in web applications - emphasis on back end APIs. Recently working in serverless applications. Enjoy speaking at tech events where possible.

Updated on October 19, 2022

Comments

  • Alex
    Alex over 1 year

    I have some classes like this:

    public class Customer
    { }
    
    public interface IRepository 
    { }
    
    public class Repository<T> : IRepository
    { }
    
    public class CustomerRepository<Customer>
    { }
    

    Then, as per the answer to this question I can use reflection to get a list of types referenced by generics for each of my *Repository:

    What I want to end up with is a Dictionary<Type, IRepository>

    So far, I have this:

    Dictionary<Type, IRepository> myRepositories = Assembly.GetAssembly(typeof(Repository<>))
    .GetTypes()
    .Where(typeof(IImporter).IsAssignableFrom)
    .Where(x => x.BaseType != null && x.BaseType.GetGenericArguments().FirstOrDefault() != null)
    .Select(
        x =>
        new { Key = x.BaseType != null ? x.BaseType.GetGenericArguments().FirstOrDefault() : null, Type = (IRepository)x })
    .ToDictionary(x => x.Key, x => x.Type);
    

    However, it doesn't like my cast (IRepository)x
    I get the following error:

    Unable to cast object of type 'System.RuntimeType' to type 'My.Namespace.IRepository'.

    • Jon Skeet
      Jon Skeet
      How are you expecting it to get an instance when you've only got a Type?