Factory method and generics

c#, factory-method, generics

Solution

I'd suggest returning the collection of repository types instead of the names and just displaying the names in the UI:

public static IEnumerable<Type> GetAvailableRepositoryClasses()
{
    return Assembly.GetExecutingAssembly().GetTypes()
        .Where(t => t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof (IRepository<>)));
}

Then when a user selects the source you can do:

object repository = Activator.CreateInstance(selectedType);

This method requires each repository to have a default constructor.

`Activator.CreateInstance` return an object, and you can't cast it to your `IRepository<T>` interface unless you know the generic type `T` you're expecting. The best solution is probably to create a non-generic `IRepository` interface which your repository classes also implement:

public interface IRepository
{
    IList<object> GetAll();
}

Now you can cast your created repositories to `IRepository`:

IRepository repository = (IRepository)Activator.CreateInstance(selectedType);

you might to create a repository base class which implements both:

public abstract class RepositoryBase<T> : IRepository<T>, IRepository
{
    public abstract IList<T> GetAll();
    IList<object> IRepository.GetAll()
    {
        return this.GetAll().Cast<object>().ToList();
    }
}

Problem

I have the following interface and implementation: ``` public interface IRepository<T> { IList<T> GetAll(); } internal class TrendDataRepository : IRepository<TrendData> { public IList<TrendData> GetAll() { //.. returns some specific data via Entity framework } } ``` I'm going to have multiple implementations that all return different data by Entity Framework. At some point I want to represent the user a list of classes that implement the IRepository interface. I do this with the following code. This works great for me. ``` public static IEnumerable<string> GetAvailableRepositoryClasses() { var repositories = from t in Assembly.GetExecutingAssembly().GetTypes() where t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof (IRepository<>)) select t.Name; return repositories; } ``` However, I would also like to create a factory method that given a specific string will return a concrete Repository type and allow me to call the 'GetAll' method on it. In pseudo-code: ``` someObject = Factory.CreateInstance("TrendData"); someObject.GetAll(); ``` (I know this won't work because I have to specify a concrete type in the factory method). I desire this functionality because I want to give a user the ability to bind a report to a specific datasource. This way they can start a new report where the datasource of the report is bound to (for example) the TrendDataRepository.GetAll() method. However, maybe because the end of the world is getting near ;-) or it's Friday afternoon and I just can't think clearly any more, I don't know how to realise this. Some pointers would be really welcomed.

Original source