【问题标题】:How to Properly configure Simple Injector with Async Tasks如何使用异步任务正确配置简单注入器
【发布时间】:2019-01-08 04:32:29
【问题描述】:

我的 ASP.NET MVC 应用程序中有自托管 WebAPI。我想在执行我的 API 操作之一时执行一些异步操作。 异步操作依赖于 DbContext 以及其他一些依赖项。

以下是我的简单注射器配置。

public class SimpleInjectorIntegrator
{
    private static Container container;

    public static Container Setup()
    {
        container = new Container();
        container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
            defaultLifestyle: new WebRequestLifestyle(),
            fallbackLifestyle: new AsyncScopedLifestyle());

        container.Register<IBaseRepository<User>, BaseRepository<User>>(Lifestyle.Scoped);
        container.Register<ComputationService>(Lifestyle.Scoped);
        container.Register<ILog, Logger>(Lifestyle.Scoped);

        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
    }

    public static T Get<T>() where T : class
    {
        if (container == null)
            throw new InvalidOperationException("Container hasn't been initialized.");

        return container.GetInstance<T>();
    }
}

Global.asax.cs 看起来像这样。

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        var container = SimpleInjectorIntegrator.Setup();
        GlobalConfiguration.Configure(WebApiConfig.Register);

        ...some other code...
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    }
}

下面是 API 控制器。

public class ExperimentUploadController : ApiController
{
    private ComputationService _service = SimpleInjectorIntegrator.Get<ComputationService>();

    public IHttpActionResult Started(InputModel model)
    {
        ...Do Something...
        var task = Task.Run(() =>
        {
             _service.Do(model.Id);
        });
    }
}

API 依赖于ComputationService,它使用存储库执行与数据库的连接。当我尝试从 ComputationService 访问数据库时,它会抛出 DbContext 已被释放。

ComputationService 代码如下所示:

public class ComputationService 
{
    private IBaseRepository<User> _userRepo = SimpleInjectorIntegrator.Get<User>();

    public void Do(int id) 
    {
        ///throws here
        var user = _userRepo.Get(id);
    }
}

我不知道为什么会这样。

【问题讨论】:

  • 您在等待task 吗?如果您不这样做,则请求可能在 Do 方法完成之前完成(并因此处理 DbContext)。
  • 我不希望线程等待任务完成。我希望我的 API 返回并让我的服务执行任务,并且在服务中我正在注入所有必需的依赖项。
  • 也许this 会有所帮助?

标签: c# asp.net-mvc dependency-injection simple-injector


【解决方案1】:

我面临的实际问题是我不希望我的 API 等待异步操作完成,因此 DbContext 正在被 @John 提到的那样处理。但是我需要 SimpleInjector 使用 AsyncScopedLifestyle 来解决依赖关系,因为我已经在我的配置中配置了它。

我使用这个Github link 找到了答案。我所做的是将我的异步方法包装在异步范围内,并在该范围内解决依赖关系,并且它起作用了。

这是更新后的代码。

public class ComputationService 
{
    private IBaseRepository<User> _userRepo;

    public void Do(int id) 
    {
        using(AsyncScopedLifestyle.BeginScope(SimpleInjectorIntegrator.Container)) 
        {
            _userRepo = = SimpleInjectorIntegrator.Container.GetInstance<User>();
            var user = _userRepo.Get(id); //works fine.
        }
    }
}

我所做的另一项更改是通过 SimpleInjectorIntegrator 类中的属性公开容器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 2019-05-31
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多