أعتقد أن @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; });
يمكنك إجراء تسجيل مزيف سيطلبه Simple Injector لكل منهما
IInstructionHandler<T>
في النظام، ولكنك تمنع تطبيقه عن طريق توفير مسند سيعود دائمًاfalse
.يمكنك استخدام المعلومات التي يوفرها Simple Injector في ملفDecoratorPredicateContext
لمعرفة نوع التنفيذ الفعلي.
بدلا من ذلك، يمكنك حقن DecoratorContext
مثيل (الإصدار 2.6 وما فوق) في أعلى مصمم الديكور (كما هو موضح هنا).ال DecoratorContext
يحتوي على نفس المعلومات الموجودة في DecoratorPredicateContext
يفعل ذلك، ولكن سيتم حقن هذا الكائن تلقائيًا بواسطة Simple Injector في مصمم الديكور الذي يعتمد عليه.فهو يسمح لك باتخاذ القرار داخل مصمم الديكور، وهو ما قد يكون مناسبًا جدًا لحالتك.
أضف ان
IDecorator
التجريد للنظام للسماح بعبور سلسلة الديكور.من خلال السماح لكل مصمم ديكور بتنفيذ أ
IDecorator
واجهة تسمح بالوصول إلى الديكور (تمامًا كما حدث هنا) يمكنك اجتياز سلسلة الديكور والعثور على نوع التنفيذ الفعلي: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);
سوف يقوم Simple Injector بحل التطبيقات المسجلة دائمًا بنفس الترتيب الذي تم تسجيلها به (وهذا مضمون).لذا، عندما تقوم بحل مجموعة من الأشياء، سيكون لديك بالفعل قائمة بالتطبيقات التي تم وضعها بنفس الترتيب.