Я думаю, что @atomaras может иметь хороший момент в вашей абстракции, хотя я думаю, что было бы хорошо, когда вы используете эту информацию в корне композиции, поскольку ваш корень композиции уже знает о каждой реализации в системе.
Я думаю, что есть несколько способов добраться до этой информации:
Использовать
DecoratorPredicateContext
информация, предоставленнаяRegisterDecorator
Метод расширения: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; });
Вы можете сделать фальшивую регистрацию, которую простой инжектор позволит на каждый
IInstructionHandler<T>
в системе, но вы не позволяете его применению, предоставив предикат, который всегда вернетсяfalse
. Анкет Вы можете использовать информацию, предоставленную простым инжектором вDecoratorPredicateContext
Чтобы выяснить, что такое реализация.
В качестве альтернативы, вы можете ввести DecoratorContext
экземпляр (v2.6 и выше) в максимальный декоратор (как объяснено здесь) А DecoratorContext
содержит ту же информацию, что и DecoratorPredicateContext
делает, но этот объект будет автоматически вводить простой инжектор в декоратор, который зависит от. Это позволяет вам принять решение внутри декоратора, что может быть очень удобно в вашем случае.
Добавить
IDecorator
Абстракция в систему, чтобы позволить пересекать цепочку декоратора.Позволяя каждому декоратору внедрить
IDecorator
интерфейс, который допускает доступ к DecorateE (так же, как это сделано здесь) вы можете пройти через цепочку декоратора и найти фактический тип реализации: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; } } }
Вы можете реализовать свои декораторы с помощью этого интерфейса следующим образом:
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; } } }
Когда вы реализовали этот интерфейс на всех ваших декораторах, вы сможете сделать это:
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()
Зарегистрировать список
Registration
экземпляры в одном изRegisterAll
перегрузки, так какRegistration
Объект знает о фактическом типе реализации.Но вместо точки 3 вы можете также использовать список типов реализации, которые вы использовали для создания этих регистраций:
typeMapping[serviceType] = implementationTypes; container.RegisterAll(serviceType, implementationTypes);
Простой инжектор разрешит зарегистрированные реализации, всегда в том же порядке, что и зарегистрировано (это гарантировано). Поэтому, когда вы разрешаете коллекцию вещей, у вас уже будет список реализаций, которые выложены в том же порядке.