Okay, this might be a softball question, but this is my first jump into the IoC in Epi, so I thought I would just ask.
Say I have a service def like this:
[ServiceConfiguration(typeof(IDocumentManagementService), Lifecycle = ServiceInstanceScope.Singleton)] public class QbankService : IDocumentManagementService
But now I am ready to reuse that interface to define another concrete class. In the places that I use that Interface, how will I tell the code to distigush WHICH implementation I want?
Do I have to have 2 seperate interfaces? Or is there a way when I'm about to either construct or service locate something concrete that I can tell it which one I want?
Have a look at this post from jondjones: http://www.jondjones.com/learn-episerver-cms/episerver-developers-guide/episerver-best-practices-tips-and-tricks/dependency-injection-in-episerver-servicelocator-and-injected-explained
At the bottom of that page he has an example with ServiceConfiguration and you can use it with ServiceLocator below:
var customImplmentation = ServiceLocator.Current.GetInstance<IDocumentManagementService>();
Yeah that's a helpful article, but I am still having trouble if there is MORE than one concrete instance of the interface.
A little Stack Overflow search seems to indicate that you can either make named instances of the interface and register them both then call them by name.
Or you can register all the instance types and pass an enumeration of the instances to the class you're injecting to.
I guess I just have trouble because I can see a situation now where I want to have 2 different types of Doc Management, but I don't WANT to have 2 different interfaces. I want them both to inherit the same interface as their contract. But with DI I have to register at the interface level and that confusses me!
As most IOC containers work is that you will get the latest registered instance when querying for a single instance like IServiceLocator.GetInstance<IMyInterface>(), if you call IServiceLocator.GetAllInstances<IMyInterface>() you will get all registered instances.
There are a bunch of alternatives if you want to control which instance that is returned when querying for a single instance. You can use ModuleDependencyAttribute on your IConfigurableModule instance to set that a specific module should execute after another one. Another alternative is to hook up an event handler for ServiceConfigurationContext.ConfigurationCompleted and in the eventhandler register the instance you want as the default one.
If you instead where to replace one registration you could use Intercept<IMyInterface>()
Yet another alterntive is to use extension method .StructureMap() and register the interfaces as named instances (named instances are supported by StructureMap). Note however that then you need to request the dependency with the registered name/key to get a specific one (I think one registration will be default and returned when asking without name/key, probably the last registered)
and keep in mind that either ServiceLocator or Injected<T> are anti-patterns and should be avoided in favor of constructor injection or any other available DI pattern (except in cases where it's absolutely is not possible).