Я думаю, что ваша предпосылка здесь немного запутана, вы говорите о внедрении фабрики, но фабричный шаблон - это творческий шаблон, целью которого было сделать подмножество того, что делает инфраструктура внедрения зависимостей, когда структуры DI не были распространены, этот шаблон был полезно по этой причине. Однако если у вас есть DI-фреймворк, вам больше не нужна фабрика, так как DI-фреймворк может выполнить задачу, которую бы выполнила фабрика.
Тем не менее, позвольте мне немного рассказать о внедрении зависимостей и о том, как вы обычно их используете.
Существует множество способов внедрения зависимостей, но наиболее распространенными являются внедрение конструкторов, внедрение свойств и прямой DIContainer. Я буду говорить о внедрении конструктора, так как внедрение свойства является неправильным подходом в большинстве случаев (правильный подход иногда), и доступ к DIContainer не является предпочтительным, за исключением случаев, когда вы абсолютно не можете использовать ни один из других подходов.
Внедрение в конструктор - это то, где у вас есть интерфейс для зависимости и DIContainer (или фабрика), который знает конкретную реализацию для этой зависимости, и всякий раз, когда вам нужен объект, который зависит от этого интерфейса, во время создания вы передаете реализацию из фабрики в Это.
т.е.
IDbConnectionProvider connProvider = DIContainer.Get<IDbConnectionProvider>();
IUserRepository userRepo = new UserRepository(connProvider);
User currentUser = userRepo.GetCurrentUser();
Многие инфраструктуры DI могут значительно упростить это, когда ваш DIContainer будет проверять конструктор UserRepository на наличие интерфейсов, для которых он знает конкретные реализации, и автоматически передает их вам; этот метод часто называют инверсией контроля, хотя DI и IoC - термины, которые сильно взаимозаменяемы и имеют неопределенные (если таковые имеются) различия.
Теперь, если вам интересно, как всеобъемлющий код обращается к DIContainer, у вас может быть статический класс для доступа к нему, или что более уместно, так это то, что большинство сред DI позволяют вам создавать DIContainer, в котором он фактически будет вести себя как Оболочка во внутренний одноэлементный словарь для типов, которые, как она знает, являются конкретными для данных интерфейсов.
Это означает, что вы можете обновлять DIContainer где угодно в коде и получать тот же DIContainer, который вы уже настроили, чтобы знать ваши связи между интерфейсом и бетоном. Обычный способ скрыть DIContainer от частей кода, которые не должны напрямую с ним взаимодействовать, состоит в том, чтобы просто гарантировать, что только необходимые проекты имеют ссылку на структуру DI.