首页 > 解决方案 > 无法访问已处置的对象 serviceProvider

问题描述

我有一个像这样的中介类,我用一堆服务初始化一个字典:

public class Mediator : IMediator
    {
        static readonly ConcurrentDictionary<int, Func<IGameBaseService>> services = new ConcurrentDictionary<int, Func<IGameBaseService>>();
        protected readonly IServiceProvider _serviceProvider;

        public Mediator(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        public async Task<Func<IGameBaseService>> GetGameServiceAsync(int gameId)
        {
            if (services.Count == 0)
                await AddServices();
            return await Task.FromResult(services[gameId]);
        }

        private async Task AddServices()
        {
            await Task.FromResult(services.GetOrAdd((int)Game.Blackjack, () => new LotteryService(_serviceProvider)));
        }

我这样调用 GetStateAsync 来获取游戏状态:

public async Task<ResponseBase> GetStateAsync(ApiGetStateInput input)
{
    var gameService = await _mediator.GetGameServiceAsync(input.Identity.GameId);
    var state = gameService().GetStateAsync(input.Identity.GameTableId);
    response.ResponseObject = state.Dump();
}

调用通过中介知道调用哪个游戏服务。它通过将 servicePrvidor 传递给构造函数来创建服务的实例。彩票游戏服务如下所示:

public class LotteryService : BaseService, IGameBaseService
    {
       public LotteryService (IServiceProvider serviceProvider) : base(serviceProvider)
        {
            
        }
    }
public Task<IEnumerable<BlGameState>> GetStateAsync(int tableId)
        {
            //logic
            return something;
        }
 public class BaseService : IBaseService
    {
        protected readonly IServiceProvider _serviceProvider;
        protected readonly IUnitOfWork _unitOfWork;
        protected readonly ICacheProvider _cache;
        protected readonly IMapper _mapper;

        public BaseService(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
            _mapper = _serviceProvider.GetService<IMapper>();
            _unitOfWork = _serviceProvider.GetService<IUnitOfWork>();
            _cache = _serviceProvider.GetService<ICacheProvider>();
        }
}

我已经在启动的 ConfigureServices 中注册了所有这些:

            services.AddAutoMapper(typeof(Startup));
            
            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped<ICacheProvider, CacheProvider>();
            services.AddScoped<IMediator, Mediator>();

问题是当我运行项目并调用 GetStateAsync 时,它工作得非常好。但是在再次调用它之后,看起来 serviceProvider 正在被处理并且无法获得 serviceProvider 实例。如何解决这个问题,有没有办法改进获取服务的代码和架构?这是错误:

Cannot access a disposed object.\r\nObject name: 'IServiceProvider'._   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()\r\n   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)\r\n   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)\r\n

标签: c#asp.net-coredependency-injectionfactory-patternmediator

解决方案


问题是您的 Mediator 是范围服务(意味着为每个请求创建一个新的服务然后处置),因为它获得的 IServiceProvider 实例在该范围内也是有效的,但是您将它保存在 LotteryService 中并在它已经处置后尝试使用它.

我可以建议一些您可以考虑的方法并选择最适合您的方法。

  1. 使 Mediator 成为单例服务
  2. 不要缓存 LotteryService 并且也使服务成为范围服务
  3. 我不知道为什么 LotteryService 需要 IServiceProvider 但也许你可以在方法调用中传递它的依赖关系

推荐阅读