Как правильно настроить простой инжектор с асинхронными задачами - PullRequest
0 голосов
/ 08 января 2019

У меня есть собственный WebAPI внутри моего приложения ASP.NET MVC. Я хочу выполнить некоторое асинхронное действие при выполнении одного из моих действий 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);
    }
}

Я не уверен, почему это происходит.

1 Ответ

0 голосов
/ 08 января 2019

Реальная проблема, с которой я столкнулся, заключалась в том, что я не хочу, чтобы мой API ожидал завершения асинхронной операции, и, следовательно, DbContext удалялся, как упомянуто @John. Но мне требуется SimpleInjector для разрешения зависимости с помощью AsyncScopedLifestyle, как я настроил его в своей конфигурации.

Я нашел ответ, используя эту ссылку Github . То, что я сделал, обернуло мой асинхронный метод в асинхронную область и разрешил зависимости в этой области, и это сработало.

Вот обновленный код.

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.

...