I have an interface (IRepository<T>) that is currently being extended for each specific repository, ie: IUserRepository : IRepository<User>.
Each of these interfaces has corresponding concrete classes, ie: UserRepository : Repository<User>, IUserRepository.
These individual repositories don't add any additional functionality, they are all empty interfaces/classes that are used simply to pass the generics around.
I use StructureMap to resolve IUserRepository into UserRepository using a Registry with an assembly scanner and some naming conventions.
I'd like this to move to a way more optimised state, where instead of passing around instances of IUserRepository and getting it resolved to UserRepository, I can pass around IRepository<User> and have it resolved to Repository<User>.
This would remove the need to create these extra empty interfaces and classes.
I can't work out a way to use StructureMap's configuration to setup this generic mapping. Something like this:
For(typeof(IRepository<>).Use(typeof(Repository<>)).WithTheGenericTypeFromTheInterfaceSuppliedAsATypeParameter(); Edit
After getting the first couple of answers, I want to clarify this a bit more.
I don't want to create individual classes for the For bit of the configuration. I want to have the following classes/interfaces in my code:
IRepository<T> where T : EntityRepository<T> : IRepository<T> where T : EntityPerson : EntityProduct : EntityOrder : EntityWhatever : EntityAnd have the following mappings achieved with convention:
IRepository<Person> => Repository<Person> IRepository<Product> => Repository<Product> IRepository<Order> => Repository<Order> IRepository<Whatever> => Repository<Whatever> But I do not want to have to create a mapping for each one, ala:
For<IRepository<Person>>().Use<Repository<Person>>(); For<IRepository<Product>>().Use<Repository<Product>>(); For<IRepository<Order>>().Use<Repository<Order>>(); For<IRepository<Whatever>>().Use<Repository<Whatever>>(); I want a single mapping that will work for any IRepository:
For<IRepository<>>().Use<Repository<>>().WithTheSameGenericType(); I would then use this to inject the repositories into services:
public MyService(IRepository<User> userRepository) And expect that to be resolved to a Repository<User> at runtime.
Turns out there is no fancy method to call, or no fancy wiring to do, you just use For and Use (the non generic versions):
public class DataRegistry : Registry { public DataRegistry() { For(typeof (IRepository<>)).Use(typeof(Repository<>)); } } When I inject a IRepository<Person> it is being resolved as a Repository<Person> now.
I encountered error 104 saying Repository wasn't pluggable for IRepository. This was because Repository was marked abstract. Making it non-abstract fixed that error and it is working as desired.
I suggest you to take a look at the AddAllTypesOf method. I had some similar code and achieved my objectives by using it (and kept the auto register feature working).
In your case, you should just change
For<IRepository<Person>>().Use<Repository<Person>>(); For<IRepository<Product>>().Use<Repository<Product>>(); For<IRepository<Order>>().Use<Repository<Order>>(); For<IRepository<Whatever>>().Use<Repository<Whatever>>(); to
AddAllTypesOf(typeof(IRepository<>)); In the end, your container will be similar to:
return new Container(x => { x.Scan(y => { y.TheCallingAssembly(); y.AddAllTypesOf(typeof(IRepository<>)); y.WithDefaultConventions(); }); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With