Внедрить с другой областью действия при использовании DbContext с пользовательским поставщиком ресурсов

В приложении у меня есть следующие компоненты (среди прочих):

  • MyDbContext: Доступ к данным Entity Framework
  • DBResourceProviderFactory: Обычай ResourceProviderFactory предоставление пользовательских IResourceProvider (называется DBResourceProvider...)
  • Другие услуги
  • StructureMap

Пользовательский поставщик ресурсов ищет ресурсы в БД, используя MyDbContext вводится так же, как описано в этом SO ответе.

MyDbContext также используется в различных других службах, и поскольку это веб-приложение, я использую StructureMaps HttpContextScoped способ ограничить время жизни MyDbContext к времени существования запроса (см. другой вопрос SO и его ответ на эту тему):

x.For<MyDbContext>().HttpContextScoped();

Тем не менее, кажется, что время жизни IResourceProvider не ограничивается одним запросом http. Следовательно, DBResourceProvider продолжает висеть на MyDbContext ссылка, которая будет удалена после первого запроса.

Как я могу справиться с этим несоответствием времени жизни - чтобы StructureMap возвращал переходный процесс MyDbContext за IDbResourceProvider при возврате экземпляров в области HttpContext во все остальные службы?

Нужны ли мне две разные реализации для этого? Интерфейс маркера? Или это плохая идея использовать Entity Framework для поиска локализованных ресурсов в первую очередь (производительность и т. Д.)?

1 ответ

Решение

Если у вас есть служба, которая имеет (или должна иметь) более длительный срок службы, чем (одна из) ее зависимостей, общее решение заключается в использовании фабрики для получения этих зависимостей.

В вашей ситуации решение может быть простым. Когда ваш DBResourceProvider определяется в корне вашей композиции вашего приложения MVC, было бы просто успешно использовать DependencyResolver.Current.GetService способ получить MyDbContext,

Когда DBResourceProvider служба не является частью корня композиции (например, потому что она содержит бизнес-логику, которую нужно протестировать), вы можете либо извлечь эту логику в свой собственный класс, чтобы позволить службе находиться в корне композиции, либо вы можете внедрить (синглтон) фабрика (например, IDbContextFactory или же Func<MyDbContext>), который позволяет вам получить правильный экземпляр, который будет решен.