ВНИМАНИЕ: этот ответ сильно устарел. Актуальную информацию см. в руководстве по интеграции.
Очень маловероятно, что какой-либо компонент будет иметь ограниченный образ жизни в одной части приложения (WCF) и действовать как переходный процесс в другой части. В вашем случае гораздо более вероятно, что ваша единица работы также должна быть ограничена в Quartz, но поскольку нет неявной области (например, HTTP-запроса, сеанса WCF и т. д.), вам придется явно начать/завершить некоторую область где выполняются операции и регистрируют их как таковые.
В Simple Injector есть несколько неявных стилей жизни с ограниченной областью действия, таких как:
WebApiRequestLifestyle
WebRequestLifestyle
WcfOperationLifestyle
Явный образ жизни scped:
LifetimeScopeLifestyle
(который определяет область действия для конкретного потока)
ExecutionContextScopingLifestyle
(который определяет область действия, зависящую от асинхронного контекста).
Поэтому при работе внутри Quartz ваша единица работы должна иметь либо LifetimeScopeLifestyle
, либо ExecutionContextScopeLifestyle
. Выбор между ними прост: если операция асинхронная и ваши методы возвращают Task<T>
, вам нужен ExecutionContextScopeLifestyle
, иначе вам нужен LifetimeScopeLifestyle
. В этом вопросе/ответе содержится дополнительная информация о том, как начать работу с Quartz, и о сроках службы.
Имея это в виду, я думаю, у вас есть три варианта:
- Рассматривайте обе службы (WCF и Quartz) как два независимых приложения, которые находятся в одном и том же AppDomain и создают два Корни композиции с собственным
SimpleInjector.Container
экземпляром. (вы также можете рассмотреть возможность разделения службы на два отдельных сервисных приложения)
- Вы отказываетесь от образа жизни WCF и явно запускаете новый
LifetimeScope
в каждой операции WCF перед разрешением службы, которая выполняет операцию.
- Рассматривайте обе службы как единое целое и используйте один корень композиции с одним контейнером, но продолжайте использовать внедрение зависимостей в своих классах обслуживания WCF. Это означает, что вам придется использовать гибридный образ жизни, чтобы получить правильный образ жизни.
Какой вариант лучше для вас, зависит от многих факторов. Например, создание двух корней композиции может быть очень простым делом, и, извлекая общие регистрации в общий метод, вы можете сделать корни композиции очень удобными в сопровождении. Все образы жизни с областью действия наследуются от ScopedLifestyle
, и это позволяет вам разрешить этому общему методу принимать ScopedLifestyle
, что позволяет общему методу не обращать внимания на то, для какой службы он вызывается. Когда это становится трудным, когда у вас есть компоненты, где на самом деле должен быть только один единственный экземпляр в полном AppDomain (поскольку Singleton
означает «один для каждого контейнера»).
Вместо того, чтобы позволить вашим службам WCF иметь какую-либо логику, вы можете сделать их действительно тонкими слоями, которые будут просто связующим звеном между WCF, вашим контейнером IOC и приложением. Таким образом, вместо того, чтобы внедрять зависимости в ваши службы WCF, вы можете просто разрешить реальную службу при вызове операции WCF:
[OperationContract]
public SomeData DoSomething() {
using (Bootstrapper.Container.BeginLifetimeScope()) {
return Bootstrapper.Container.GetInstance<IDoSomethingService>()
.DoSomething();
}
}
Это позволяет вам зарегистрировать все компоненты области действия с одним и тем же LifetimeScopeLifestyle
. Эта модель работает очень хорошо, когда у вас есть архитектура, управляемая сообщениями, поскольку это означает, что ваш уровень WCF будет состоять не более чем из двух методов, которые можно прочитать здесь. Этот подход может упростить задачу, поскольку WcfOperationLifestyle
имеет несколько неожиданное поведение, потому что он кэширует службы не «для каждой операции WCF», а на время действия класса обслуживания WCF (класса, содержащего эти методы операций), и в в конце концов, именно WCF и ваша конфигурация определяют, как долго должна жить такая служба. Это может быть PerCall
, PerSession
или даже Single
.
Недостатком этого подхода, однако, является то, что если у вас есть очень широкая служба WCF (со многими методами), вам, вероятно, потребуется много рефакторинга, чтобы добраться до этого, и много церемоний в ваших классах службы WCF.
Третий вариант — использовать гибридный образ жизни следующим образом:
ScopedLifestyle hybridLifestyle = Lifestyle.CreateHybrid(
container.GetCurrentWcfOperationScope() != null,
new WcfOperationLifestyle(),
new LifetimeScopeLifestyle());
container.Register<IUnitOfWork, UnitOfWork>(hybridLifestyle);
Вы можете использовать этот hybridLifestyle
как образ жизни для регистрации ваших экземпляров. Это позволяет вашей конфигурации работать как с WCF, так и вне WCF. Это, конечно, означает, что вам придется явно запускать область действия, как описано здесь.
person
Steven
schedule
01.04.2014