Creo que @atomaras podría tener un buen punto sobre su abstracción, aunque creo que estaría bien cuando solo use esta información dentro de su raíz de composición, ya que su raíz de composición ya está al tanto de cada implementación en el sistema.
Creo que hay algunas formas de llegar a esta información:
Utilizar el
DecoratorPredicateContext
información que se suministra alRegisterDecorator
Método de extensión:var typeMapping = new Dictionary<Type, Type>(); container.RegisterDecorator(typeof(IInstructionHandler<>), typeof(FakeDecorator<>), c => { typeMapping[c.ServiceType] = c.ImplementationType; // or perhaps even use c.AppliedDecorators property to see which decorators // are applied. // return false to prevent the decorator from being applied. return false; });
Puede hacer un registro falso que el inyector simple llamará para cada
IInstructionHandler<T>
en el sistema, pero evita que se aplique suministrando un predicado que siempre regresaráfalse
. Puede usar la información suministrada por un inyector simple en elDecoratorPredicateContext
Para averiguar cuál es la implementación real del Type.
Alternativamente, puede inyectar un DecoratorContext
instancia (v2.6 y arriba) en el más decorador (como se explicó aquí). los DecoratorContext
contiene la misma información que el DecoratorPredicateContext
lo hace, pero este objeto será inyectado automáticamente por un inyector simple en un decorador que depende. Le permite tomar la decisión dentro de un decorador, lo que podría ser muy conveniente en su caso.
Agrega un
IDecorator
Abstracción al sistema para permitir atravesar la cadena del decorador.Dejando que cada decorador implementa un
IDecorator
interfaz que permite el acceso al decorado (tal como lo hizo aquí) Puede atravesar la cadena del decorador y encontrar el tipo de implementación real:public interface IDecorator { object Decoratee { get; } } public static class DecoratorHelpers { public static IEnumerable<object> GetDecoratorChain(IDecorator decorator) { while (decorator != null) { yield return decorator; decorator = decorator.Decoratee as IDecorator; } } }
Puede implementar sus decoradores con esta interfaz de la siguiente manera:
public class SomeDecorator<T> : IInstructionHandler<T>, IDecorator { private readonly IInstructionHandler<T> decoratee; public SomeDecorator(IInstructionHandler<T> decoratee) { this.decoratee = decoratee; } object IDecorator.Decoratee { get { return this.decoratee; } } }
Cuando implementó esta interfaz en todos sus decoradores, podrá hacer esto:
var implementationTypes = from handler in container.GetAllInstances<IInstructionHandler<RenderWord>>() let mostInnerDecorator = DecoratorHelpers.GetDecoratorChain(handler as IDecorator).LastOrDefault() let implementation = mostInnerDecorator != null ? mostInnerDecorator.Decoratee : handler select implementation.GetType()
Registre una lista de
Registration
instancias en uno de losRegisterAll
sobrecargas, desde elRegistration
Object sabe sobre el tipo de implementación real.Pero en lugar del punto 3, también podría usar la lista de tipos de implementación que usó para crear esos registros:
typeMapping[serviceType] = implementationTypes; container.RegisterAll(serviceType, implementationTypes);
El inyector simple resolverá las implementaciones registradas siempre en el mismo orden que están registrados (esto está garantizado). Entonces, cuando resuelva una colección de cosas, ya tendrá la lista de implementaciones que se presentan en el mismo orden.