Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

reflection

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'.

like image 413
Alex Avatar asked Sep 17 '12 17:09

Alex


2 Answers

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 );
like image 123
cuongle Avatar answered Nov 01 '22 09:11

cuongle


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?

like image 32
Jeppe Stig Nielsen Avatar answered Nov 01 '22 09:11

Jeppe Stig Nielsen