如何使用异步任务正确配置简单注入器

时间:2019-01-08 04:32:29

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

我在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,该API使用存储库执行与数据库的连接。当我尝试从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);
    }
}

我不确定为什么会这样。

1 个答案:

答案 0 :(得分:0)

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

我使用此Github link找到了答案。我所做的是将我的Asynchronous方法包装在Asynchronous范围内,并解决了该范围内的依赖关系,并且有效。

这是更新的代码。

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类中的Property公开Container。