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.
I’d suggest returning the collection of repository types instead of the names and just displaying the names in the UI:
Then when a user selects the source you can do:
This method requires each repository to have a default constructor.
Activator.CreateInstancereturn an object, and you can’t cast it to yourIRepository<T>interface unless you know the generic typeTyou’re expecting. The best solution is probably to create a non-genericIRepositoryinterface which your repository classes also implement:Now you can cast your created repositories to
IRepository:you might to create a repository base class which implements both: