using System.Threading; using Abp.Dependency; using Castle.Core; using Castle.Core.Logging; namespace Abp.Domain.Uow { /// /// CallContext implementation of . /// This is the default implementation. /// public class AsyncLocalCurrentUnitOfWorkProvider : ICurrentUnitOfWorkProvider, ITransientDependency { /// [DoNotWire] public IUnitOfWork Current { get { return GetCurrentUow(); } set { SetCurrentUow(value); } } public ILogger Logger { get; set; } private static readonly AsyncLocal AsyncLocalUow = new AsyncLocal(); public AsyncLocalCurrentUnitOfWorkProvider() { Logger = NullLogger.Instance; } private static IUnitOfWork GetCurrentUow() { var uow = AsyncLocalUow.Value?.UnitOfWork; if (uow == null) { return null; } if (uow.IsDisposed) { AsyncLocalUow.Value = null; return null; } return uow; } private static void SetCurrentUow(IUnitOfWork value) { lock (AsyncLocalUow) { if (value == null) { if (AsyncLocalUow.Value == null) { return; } if (AsyncLocalUow.Value.UnitOfWork?.Outer == null) { AsyncLocalUow.Value.UnitOfWork = null; AsyncLocalUow.Value = null; return; } AsyncLocalUow.Value.UnitOfWork = AsyncLocalUow.Value.UnitOfWork.Outer; } else { if (AsyncLocalUow.Value?.UnitOfWork == null) { if (AsyncLocalUow.Value != null) { AsyncLocalUow.Value.UnitOfWork = value; } AsyncLocalUow.Value = new LocalUowWrapper(value); return; } value.Outer = AsyncLocalUow.Value.UnitOfWork; AsyncLocalUow.Value.UnitOfWork = value; } } } private class LocalUowWrapper { public IUnitOfWork UnitOfWork { get; set; } public LocalUowWrapper(IUnitOfWork unitOfWork) { UnitOfWork = unitOfWork; } } } }