Penso che @atomaras potrebbe avere un buon punto sulla tua astrazione, anche se penso che andrebbe bene quando usi queste informazioni solo all'interno della radice della tua composizione, poiché la radice della composizione è già a conoscenza di ogni implementazione nel sistema.
Penso che ci siano alcuni modi per raggiungere queste informazioni:
Utilizzare il
DecoratorPredicateContext
informazioni fornite al fileRegisterDecorator
Metodo di estensione: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; });
Puoi effettuare una falsa registrazione che il semplice iniettore richiederà ogni
IInstructionHandler<T>
Nel sistema, ma si impedisce che venga applicato fornendo un predicato che tornerà semprefalse
. È possibile utilizzare le informazioni fornite da un semplice iniettore inDecoratorPredicateContext
Per scoprire qual è l'effettivo ImplementationType.
In alternativa, puoi iniettare un DecoratorContext
istanza (v2.6 e su) nella parte superiore più decoratrice (come spiegato qui). Il DecoratorContext
contiene le stesse informazioni del DecoratorPredicateContext
fa, ma questo oggetto verrà automaticamente iniettato da un semplice iniettore in un decoratore da cui dipende. Ti consente di prendere la decisione all'interno di un decoratore, che potrebbe essere molto comodo nel tuo caso.
Aggiungi un an
IDecorator
astrazione al sistema per consentire la attraversamento della catena del decoratore.Lasciando che ogni decoratore implementa un file
IDecorator
interfaccia che consente l'accesso al decorazione (proprio come fatto qui) puoi attraversare la catena del decoratore e trovare il tipo di implementazione effettivo: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; } } }
Puoi implementare i tuoi decoratori con questa interfaccia come segue:
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 hai implementato questa interfaccia su tutti i tuoi decoratori, sarai in grado di farlo:
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()
Registra un elenco di
Registration
istanze in uno deiRegisterAll
sovraccarico, dal momento cheRegistration
Oggetto è a conoscenza del tipo di implementazione effettivo.Ma invece del punto 3, potresti anche utilizzare l'elenco dei tipi di implementazione che hai usato per creare tali registrazioni:
typeMapping[serviceType] = implementationTypes; container.RegisterAll(serviceType, implementationTypes);
L'iniettore semplice risolverà le implementazioni registrate sempre nello stesso ordine in cui sono registrate (questo è garantito). Quindi, quando risolvi una raccolta di cose, avrai già l'elenco delle implementazioni che viene definita nello stesso ordine.