May 31, 2014 02:23 PM|Louis DeJardin|LINK
ITypeActivator isn't a central interface which is required of conforming containers. Rather, it's the code that we found to was common between the various places where a class was being instantiated wihch wasn't itself registered as a service. In other words
- it's not implemented by the container or a constraint of the container, it's a helper where you would have cut and paste the same reflection code that call.
We will also very likely have IControllerActivator and IViewActivator to override those cases specifically. In those cases the default implementation will likely depend on ITypeActivator.
The approach we took was not to bring all containers down to a lowest common denominator, but we did need to establish what the least set of container behavior our components were limited to assuming were present. By limiting out components to this
set of behaviors they can be registered and function properly when registered into any application's IoC container if they bring one to the table. However, because the application itself knows what container it is using, it's own startup code and components
are free to use the full api and feature set of the container in question.
That is nothing new of course. It's just how you make IoC friendly components.
The place we did define a common representation of an IoC concept, in order for our frameworks to be more easily added to arbitraty containers, was IServiceDefinition. Our frameworks are able to provide the list of default services they are based on when
asked, and it's done in a way that's meant to be looped through and registered into your container through the container-specific apis. That is also common code, so when you see things like support for Windsor it's that code the application would need to write
that loops though a set of IServiceDefinition and registers them in that container.
That said - the application itself does not need to use define it's own components through IServiceDefinition. Instead I'm certain you'd use the container's own api to add all of the application's components and services.
The tricky part is finding the balance around what set of behaviors are safe to assume can be provided by the containers people will want to use around our components. So far those are something along these lines
* constructor injection of service interfaces
* service IEnumerable<T> is a way to have multiple, or optional, service T
* open generic services and implementations will be closed when needed typeof(IHello<>) typeof(Hello<>) will give you Hello<string> when you resolve IHello<string>
* in the unfortunate case that a service must be resolved in a lazy fashion, the existing System.IServiceProvider is constructor injected. the container does not need to implement this interface, but a component that implements IServiceProvider must be registered,
which returns a calls to the container's native api to resolve
* there is a way to create and dispose a child scope for resolving components, this is used most obviously in the place where the web stack creates a per-request container
* chaining - this is the most complex one actually. because the "hosting" offers it's default capabilities as an IServiceProvider to the application, it's assumed that the application created IoC container can be created in a way where an unknown service
will fallback as a call to the host's IServiceProvider. Because this chaining is tricky to set up correctly, that's also something we put in the code that registers the IServiceDescriptor array into a specific container.
It's also assumed that when an IoC container has it's own additional library to do this setup, then we won't need to provide a ms library with that code. That would be similar to how most containers have some sort of additional library with code specific
to using it with web api, mvc, etc.