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.