Краткий ответ
Вы пытаетесь заставить DI Контейнер (Castle Windsor) выполнять функцию композицию, но на самом деле он нацелен на объект композицию. Это просто даст вам много трений. Я предполагаю, что вы получите такой же опыт с другими контейнерами.
Контейнеры DI разработаны на основе объектно-ориентированных концепций, в частности, SOLID. Они очень хорошо работают с этими принципами, потому что они были разработаны с присущим пониманием таких вещей, как инжектор конструктора и автоматическое подключение.
В более функциональном подходе нет ничего плохого, но мне еще предстоит увидеть DI-контейнер, построенный вокруг композиции функций, а не композиции объектов.
Длинный ответ
Использование делегатов в качестве общего принципа для DI, как правило, проблематично в статически типизированных языках (по крайней мере, в .NET) по нескольким причинам. Концептуально в этом подходе нет ничего плохого, поскольку делегат можно рассматривать как анонимный интерфейс роли . Тем не менее, он становится громоздким из-за неоднозначности типов.
Наиболее распространенный подход, который я обычно вижу, - это использование встроенных делегатов BCL, таких как Func<T>
, Action<T>
и так далее. Тем не менее, у вас может быть много разных потребителей, которые полагаются на Func<string>
, и в этом случае вещи становятся неоднозначными - просто потому, что потребитель требует Func<string>
, не означает, что он требует делегата в той же роли. Хотя механически возможно использовать DI с делегатами, получается, что делегаты скрывают роли приложения . Роли исчезают, оставляя только механику.
Затем вы можете, как предложено в OP, определить пользовательские делегаты для каждой роли, как предложено этим делегатом:
public delegate IEnumerable<Product> DGetProducts();
Однако, если вы выберете этот путь, то ничего не получите. «Делегат роли» должен быть определен для каждой роли. Сравните это с определением подобного интерфейса, и должно быть ясно, что единственное сохранение - это пара угловых скобок и явное определение метода:
public interface IProductSource { IEnumerable<Product> GetProducts(); }
Это не много накладных расходов (если есть).
Вы также можете посмотреть это обсуждение: http://thorstenlorenz.wordpress.com/2011/07/23/dependency-injection-is-dead-long-live-verbs/