使用WebApi、SimpleInjector和Mediator时正确设置Scope

本文关键字:设置 Scope Mediator WebApi SimpleInjector 使用 | 更新日期: 2023-09-27 18:08:23

控制器

public class LocationsController : ApiController
{
    private readonly IMediator _mediator;
    public LocationsController(IMediator mediator)
    {
        _mediator = mediator;
    }
    public IEnumerable<Place> Get()
    {
        return _mediator.Send(new GetLatestMapData<Place>());
    }
}

在第一次请求Get((操作时,SimpleInjector会实例化处理程序并正确执行。

在第二次请求时(例如,浏览器中的F5(,它失败,并显示:

找不到类型为…的请求的处理程序。。。。

容器或服务定位器配置不正确,或者处理程序未在容器中注册。

和内部异常:

无法访问已释放的对象。

对象名称:"ThreadLocal对象已被释放。">

OWIN启动

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // SimpleInjector
        var container = CompositionRoot.CreateContainer();
        var config = GlobalConfiguration.Configuration;
        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
        // Routing
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}",
            new { id = RouteParameter.Optional });
        config.EnsureInitialized();
        app.UseWebApi(config);
    }
}

WebAPI项目的SimpleInjector IP包

public class Installer : IPackage
{
    public void RegisterServices(Container c)
    {
        c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
        c.RegisterWebApiControllers(GlobalConfiguration.Configuration);
    }
}

我认为发生的事情是正确地创建了处理程序,然后在第一个请求之后进行处理。现在,我不知道为什么,但在随后的请求中,不会重新创建处理程序。我知道这一点,因为如果我将WebApiRequestLifestyle更改为"范围结束时不处置",它适用于每个请求:

c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(false
/*disposeInstanceWhenScopeEnds*/);

问题

  1. 我应该将disposeInstanceWhenScopeEnds参数设置为false吗
  2. 如果没有,正确的解决方案是什么
  3. 我看到这个问题以前已经通过创建LifetimeScopeRecorder解决了。。。但是,这个功能肯定已经由SimpleInjector WebApi集成库提供了吗?我错过了什么

(感谢您的阅读(

使用WebApi、SimpleInjector和Mediator时正确设置Scope

此链接提供了有关依赖项解析和使用IDependencyResolver/IDependencyScope接口的良好指导。

你会立刻发现,它们涉及的寿命往往会变得有点棘手。

这一部分特别有趣:

依赖范围和控制器寿命

控制器是根据请求创建的。为了管理对象寿命,IDdependencyResolver使用范围的概念。

附加到HttpConfiguration对象的依赖关系解析程序具有全球范围。当Web API创建一个控制器时,它会调用BeginScope。此方法返回一个表示子作用域的IDependencyScope。

然后Web API在子作用域上调用GetService以创建控制器。当请求完成时,Web API在子范围。使用Dispose方法处理控制器的依赖关系。

按照惯例,引导服务会在应用程序启动期间发生一次,并且如您所知,会在那时解决任何依赖关系。只有当工作进程关闭时(例如,没有活动(,才会调用dispose。

通常,我认为已解决的实例在生命周期中保留是很正常的,除非它们在使用后必须销毁。但是,给出的示例说明,一旦请求完成,我们就必须正确处理。因此,我建议您使用所提供的示例作为指导,正确处理您的实例。

这对我使用IoC和WebApi时有所帮助。我希望这能有所帮助!

您需要安排您的Lifetime范围

代码:

container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
container.Options.LifestyleSelectionBehavior = new WebApiInjectionLifestyle();

internal class WebApiInjectionLifestyle : ILifestyleSelectionBehavior
{
    public Lifestyle SelectLifestyle(Type serviceType, Type implementationType)
    {
        return Lifestyle.Scoped;
    }
}

更多详细

https://simpleinjector.readthedocs.io/en/latest/lifetimes.html