Eu acho que o @atomaras pode ter um bom ponto sobre sua abstração, embora eu ache que tudo ficaria bem quando você usa essas informações dentro da raiz da composição, pois sua raiz de composição já está ciente de todas as implementações do sistema.
Eu acho que existem algumas maneiras de chegar a essas informações:
Use o
DecoratorPredicateContext
informações que são fornecidas aoRegisterDecorator
Método de extensão: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; });
Você pode fazer um registro falso que o simples injetor exigirá para cada
IInstructionHandler<T>
No sistema, mas você evita que ele seja aplicado fornecendo um predicado que sempre retornaráfalse
. Você pode usar as informações fornecidas por injetor simples noDecoratorPredicateContext
Para descobrir qual é o implementação real.
Como alternativa, você pode injetar um DecoratorContext
instância (v2.6 ou mais) no topo mais decorador (conforme explicado aqui). o DecoratorContext
contém a mesma informação que o DecoratorPredicateContext
Faz, mas esse objeto será automaticamente injetado pelo injetor simples em um decorador que depende. Ele permite que você tome a decisão dentro de um decorador, o que pode ser muito conveniente no seu caso.
Adicione um
IDecorator
Abstração no sistema para permitir atravessar a corrente do decorador.Permitindo que cada decorador implemente um
IDecorator
interface que permite o acesso ao decorado (exatamente como feito aqui) Você pode atravessar a corrente do decorador e encontrar o tipo de implementação 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; } } }
Você pode implementar seus decoradores com esta interface da seguinte forma:
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; } } }
Quando você implementou essa interface em todos os seus decoradores, você poderá fazer isso:
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()
Registrar uma lista de
Registration
instâncias em um dosRegisterAll
sobrecarga, já que oRegistration
Objeto conhece o tipo de implemenação real.Mas, em vez do ponto 3, você também pode usar a lista de tipos de implemenação que usou para criar esses registros:
typeMapping[serviceType] = implementationTypes; container.RegisterAll(serviceType, implementationTypes);
O Injetor Simples resolverá as implementações registradas sempre na mesma ordem em que estão registradas (isso é garantido). Portanto, quando você resolver uma coleção de coisas, você já terá a lista de implementações que são apresentadas na mesma ordem.