autofac/Autofac — pull request #606 by ilya-g (2014-12-17 00:43:23+00:00)
Title: Preserve correct order of service registration in the nested component registry

This pull request provides the solution for issue #272.

**Requirements**
The key to resolve this issue is to ensure the correct order of the service implementations in `ServiceRegistrationInfo` class, since the first one of them is treated as default one.
To figure out which order is correct I was using the following assumptions:
- *default* registration always override all registrations made before, including those from parent scope
- *preserve-default* registration is always overridden by registrations made before. It's used as default only if there are no registrations made before.

So the correct order is one where in the beginning there are default explicit registrations made in nested scope, then registrations coming from sources, such as parent registry, and then in the end explicit preserve-default registrations.
These implementations in the middle from the parent registries must also be in the correct order, so that in case if the nested scope doesn't override the default implementation, the default one must be same as in the parent registry. The latter requirement was hard to implement due to the way parent registries were queried for registrations.
A parent registry is added as the `ExternalRegistrySource` to the nested one. The source takes all non-adapting registrations from the registry and wraps them to coerce some of their properties. But this means that on the next level of hierarchy these wrapped registrations are excluded as adapting-ones when being queried by `ExternalRegistrySource` (probably, to prevent double wrapping). Therefore to get the all service implementations you have to traverse up the whole hierarchy and query every parent source for registrations. It becomes very hard to reconstruct the correct order of implementations when adding each provided implementation one by one.

**Changes**
So I've decided to change the way `ExternalRegistrySource` works. Now it doesn't exclude implementations wrapped by the parent registry. To distinguish these wrapped implementation from the adapting ones I've subtyped `ComponentRegistration` class. This also prevents double registration wrapping, 'cause such subtyped `ExternalComponentRegistartion` class can be shared between all the nested registries down to hierarchy.

**Questions**
One thing left unclear to me is the relation between *preserve-defaults* registrations and the registrations originated from sources. There are two mutually exclusive options:
1. Preserve-default registrations are always superseded by the other registrations, even those from sources.
2. The sources are consulted for registration only if there is no any explicit registration made to the registry, including preserve-default one. This means preserve-default registration takes precedence over that which was originated from registration source.
Can someone provide the answer (would be better if it's backed up with the reference to some existing docs)?

In the latter case we'll need to distinguish somehow `ExternalRegistrySource` from the other source types when initializing `ServiceRegistrationInfo`.

**TODOs**
I've introduced a new requirement for `IComponentRegistry.RegistrationsFor` method implementation. It must return the sequence, starting with the default implementation of the service. This requirement was fulfilled de-facto, but I think some new unit tests or assertions in existing tests should be made to ensure the default implementation (`ComponentRegistry`) behavior is correct.