Je pense que @atomaras pourrait avoir un bon point sur votre abstraction, bien que je pense que ce serait bien lorsque vous n'utilisez ces informations que dans votre racine de composition, car votre racine de composition est déjà consciente de chaque implémentation du système.
Je pense qu'il y a plusieurs façons d'accéder à ces informations:
Utilisez le
DecoratorPredicateContext
informations fournies auRegisterDecorator
Méthode d'extension: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; });
Vous pouvez effectuer un faux enregistrement que l'injecteur simple appellera pour chaque
IInstructionHandler<T>
dans le système, mais vous empêchez son application en fournissant un prédicat qui reviendra toujoursfalse
. Vous pouvez utiliser les informations fournies par un simple injecteur dans leDecoratorPredicateContext
Pour savoir quel est le Type d'implémentation réel.
Alternativement, vous pouvez injecter un DecoratorContext
Instance (v2.6 et plus) dans le décorateur le plus haut (comme expliqué ici). La DecoratorContext
contient les mêmes informations que le DecoratorPredicateContext
Le fait, mais cet objet sera automatiquement injecté par un simple injecteur dans un décorateur qui dépend. Il vous permet de prendre la décision à l'intérieur d'un décorateur, ce qui pourrait être très pratique dans votre cas.
Ajouter un
IDecorator
Abstraction au système pour permettre la traversée de la chaîne de décorateur.En laissant chaque décorateur mettre en œuvre un
IDecorator
interface qui permet d'accéder au décoré (tout comme fait ici) Vous pouvez traverser la chaîne de décorateur et trouver le type de mise en œuvre réel: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; } } }
Vous pouvez implémenter vos décorateurs avec cette interface comme suit:
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; } } }
Lorsque vous avez mis en œuvre cette interface sur tous vos décorateurs, vous pourrez le faire:
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()
Enregistrer une liste de
Registration
instances dans l'un desRegisterAll
surcharge, puisque leRegistration
L'objet connaît le type d'imprégération réel.Mais au lieu du point 3, vous pourriez aussi bien utiliser la liste des types de mise en œuvre que vous avez utilisés pour créer ces enregistrements:
typeMapping[serviceType] = implementationTypes; container.RegisterAll(serviceType, implementationTypes);
L'injecteur simple résoudra toujours les implémentations enregistrées dans le même ordre qu'elles sont enregistrées (ceci est garanti). Ainsi, lorsque vous résolvez une collection de choses, vous aurez déjà la liste des implémentations qui est présentée dans le même ordre.