IServiceProvider.GetService静默崩溃

时间:2019-07-10 12:54:50

标签: c# asp.net-core dependency-injection .net-core async-await

我有一个带有自定义映射器集的项目,该映射器在模型和视图模型之间进行映射。每个映射器都可以访问IServiceProvider以便为其内部对象获取相应的映射器。像这样:

public class OuterMapper : MapperBase<OuterModel, OuterViewModel>
{
    public OuterMapper(IServiceProvider serviceProvider, IMyDbContext dbContext)
        : base(serviceProvider, dbContext)
        {}

    public override async Task<OuterModel> ToModel(OuterViewModel viewModel, OuterModel existingModel)
    {
        var model = existingModel
            ?? (await base.DbContext.OuterModels.SingleAsync(x => x.Id == viewModel.Id))
            ?? new OuterModel();
        model.SimpleProperty = viewModel.SimpleProperty;
        model.InnerComplexObject = await base.ToInnerModel(viewModel.InnerComplexObject, model.InnerComplexObject);

        return model;
    }

    public override async Task<OuterViewModel> ToViewModel(OuterModel model, OuterViewModel existingViewModel)
    {
        var viewModel = existingViewModel ?? new OuterViewModel();
        viewModel.SimpleProperty = model.SimpleProperty;
        viewModel.InnerComplexObject = await base.ToInnerViewModel(model.InnerComplexObject, viewModel.InnerComplexObject);

        return viewModel;
    }
}

public abstract class MapperBase<TModel, TViewModel> : IMapper<TModel, TViewModel>
{
    private IServiceProvider ServiceProvider { get; set; }
    protected IMyDbContext DbContext { get; private set; }

    public MapperBase(IServiceProvider serviceProvider, IMyDbContext dbContext)
    {
        ServiceProvider = serviceProvider;
        DbContext = dbContext;
    }

    protected async Task ToInnerModel<TInnerModel, TInnerViewModel>(TInnerViewModel viewModel, TInnerModel model)
    {
        var innerMapper = ServiceProvider.GetService<IMapper<TInnerModel, TInnerViewModel>>();
        return await innerMapper.ToModel(viewModel, model);
    }

    protected async Task ToInnerViewModel<TInnerModel, TInnerViewModel>(TInnerModel model, TInnerViewModel viewModel)
    {
        var innerMapper = ServiceProvider.GetService<IMapper<TInnerModel, TInnerViewModel>>();
        return await innerMapper.ToViewModel(model, viewModel);
    }
}

最近,我们已经开始将代码重构,以从同步操作转变为异步操作(如示例映射程序中已经看到的那样)。但是,这导致了不可预测的附带问题。当映射具有很多嵌套对象的非常复杂的对象时,有时会在下面的代码行中出现静默崩溃:

var innerMapper = ServiceProvider.GetService<IMapper<TInnerModel, TInnerViewModel>>();

基本上,该应用程序似乎已冻结,无法响应新请求。似乎某个地方有一个尚未等待的异步方法,但我们还没有找到任何异步方法。当评估表达式时(在JetBrains Rider中),我收到超时错误消息。我对IServiceProvider进行了自省,可以看到其中的ResolvedServices中有一个正确的映射器实例。此外,当我将具有完全相同类型参数的问题行移到项目的另一部分(例如,直接移到控制器中)时,映射器将按预期解决。

可能是什么原因导致此问题? ASP.NET Core中有ServiceProvider个调用限制吗?

仅需几个细节:我使用的是.NET Core 2.2,它在Windows 10计算机上运行,​​并使用JetBrains Rider进行开发。

编辑

我使用了JetBrains Rider的“调试外部源”功能,并浏览了一些.NET代码。最后一次致电是在第29-31行打到Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService,其中this._disposed被评估为true。然后,最后一行是ThrowHelper.ThrowObjectDisposedException(),此后应用程序冻结。为什么要处置提供者?为什么没有捕获异常?

0 个答案:

没有答案
相关问题