Ich denke, @atomaras hat vielleicht einen guten Punkt für Ihre Abstraktion, obwohl ich denke, dass es in Ordnung wäre, wenn Sie diese Informationen nur in Ihrer Kompositionsroste verwenden, da Ihre Kompositionswurzel bereits jede Implementierung im System kennen.
Ich denke, es gibt ein paar Möglichkeiten, um diese Informationen zu erreichen:
Verwenden Sie das
DecoratorPredicateContext
Informationen, die an die geliefert werdenRegisterDecorator
Erweiterungsmethode: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; });
Sie können eine gefälschte Registrierung vornehmen, die einfache Injektor für jeden anruft
IInstructionHandler<T>
im System, aber Sie verhindern, dass es angewendet wird, indem Sie ein Prädikat liefern, das immer zurückkehrtfalse
. Sie können die von einfachen Injektoren in der gelieferten Informationen verwendenDecoratorPredicateContext
Um herauszufinden, was der tatsächliche Implementierungstyp ist.
Alternativ können Sie eine injizieren DecoratorContext
Instanz (v2.6 und up) in den obersten Dekorateur (wie erklärt hier). Das DecoratorContext
enthält die gleichen Informationen wie die DecoratorPredicateContext
tut, aber dieses Objekt wird automatisch von einem einfachen Injektor in einen Dekorateur injiziert, von dem abhängig ist. Sie können die Entscheidung in einem Dekorateur treffen, was in Ihrem Fall möglicherweise sehr bequem ist.
Füge ein an hinzu
IDecorator
Abstraktion zum System, um die Dekorateurkette zu durchqueren.Indem jeder Dekorateur a implementiert wird
IDecorator
Schnittstelle, die den Zugriff auf die Dekoration ermöglicht (genau wie getan hier) Sie können die Dekorationskette durchqueren und den tatsächlichen Implementierungstyp finden: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; } } }
Sie können Ihre Dekorateure mit dieser Oberfläche wie folgt implementieren:
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; } } }
Wenn Sie diese Benutzeroberfläche für alle Ihre Dekorateure implementiert haben, können Sie dies tun:
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()
Registrieren Sie eine Liste von
Registration
Instanzen in einem derRegisterAll
Überlastungen, seit derRegistration
Objekt kennt den tatsächlichen Implemedierungstyp.Anstelle von Punkt 3 können Sie auch die Liste der Implementierungstypen verwenden, mit denen Sie diese Registrierungen erstellt haben:
typeMapping[serviceType] = implementationTypes; container.RegisterAll(serviceType, implementationTypes);
Einfacher Injektor löst die registrierten Implementierungen immer in der gleichen Reihenfolge wie registriert (dies ist garantiert). Wenn Sie also eine Sammlung von Dingen lösen, haben Sie bereits die Liste der Implementierungen, die in derselben Reihenfolge festgelegt sind.