public IEnumerable <Action <IConsumeContext <TMessage> > > GetSaga <TMessage>(IConsumeContext <TMessage> context, Guid sagaId, InstanceHandlerSelector <TSaga, TMessage> selector, ISagaPolicy <TSaga, TMessage> policy) where TMessage : class { bool needToLeaveSagas = true; Monitor.Enter(_sagas); try { TSaga instance = _sagas[sagaId]; if (instance == null) { if (policy.CanCreateInstance(context)) { instance = policy.CreateInstance(context, sagaId); _sagas.Add(instance); lock (instance) { Monitor.Exit(_sagas); needToLeaveSagas = false; yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Creating New {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { _sagas.Remove(instance); } } catch (Exception ex) { var sex = new SagaException("Create Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } throw sex; } }); } } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Missing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } else { if (policy.CanUseExistingInstance(context)) { Monitor.Exit(_sagas); needToLeaveSagas = false; lock (instance) { yield return(x => { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Using Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } try { foreach (var callback in selector(instance, x)) { callback(x); } if (policy.CanRemoveInstance(instance)) { _sagas.Remove(instance); } } catch (Exception ex) { var sex = new SagaException("Existing Saga Instance Exception", typeof(TSaga), typeof(TMessage), sagaId, ex); if (_log.IsErrorEnabled) { _log.Error(sex); } throw sex; } }); } } else { if (_log.IsDebugEnabled) { _log.DebugFormat("SAGA: {0} Ignoring Existing {1} for {2}", typeof(TSaga).ToFriendlyName(), sagaId, typeof(TMessage).ToFriendlyName()); } } } } finally { if (needToLeaveSagas) { Monitor.Exit(_sagas); } } }