[英]Correctly set Scope when using WebApi, SimpleInjector and MediatR
控制者
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()操作時,Handler將由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 IPackage
public class Installer : IPackage
{
public void RegisterServices(Container c)
{
c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
c.RegisterWebApiControllers(GlobalConfiguration.Configuration);
}
}
我認為正在發生的是正確創建了Handler,然后在第一個請求之后將其處置。 現在,我不知道為什么,但是在后續請求中,不會重新創建處理程序。 我知道這是因為,如果我將WebApiRequestLifestyle更改為“作用域結束時不處置”,則它適用於每個請求:
c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(false
/*disposeInstanceWhenScopeEnds*/);
問題
disposeInstanceWhenScopeEnds
參數設置為false? (感謝您的閱讀)
該鏈接提供了有關依賴關系解析和使用IDependencyResolver / IDependencyScope接口的良好指南。
立刻,您會發現它們觸及到壽命,這往往會有些棘手。
本節特別有趣:
依賴范圍和控制器壽命
控制器是根據請求創建的。 為了管理對象生存期,IDependencyResolver使用范圍的概念。
附加到HttpConfiguration對象的依賴項解析器具有全局作用域。 Web API創建控制器時,它將調用BeginScope。 此方法返回代表子范圍的IDependencyScope。
然后,Web API在子作用域上調用GetService來創建控制器。 請求完成后,Web API會在子范圍上調用Dispose。 使用Dispose方法處理控制器的依賴項。
按照慣例,引導服務會在應用程序啟動期間發生一次,並且您知道當時可以解決所有依賴關系。 只有當工作進程關閉時(例如,沒有活動),才可以調用Dispose。
通常,我認為解決實例在生命周期中保留是很正常的,除非必須在使用后銷毀它們。 但是給出的示例說明,一旦請求完成,我們必須正確處理。 因此,我建議您使用提供的示例作為指導正確處置實例。
在使用IoC和WebApi時,這對我有幫助。 我希望這有幫助!
您需要安排您的終身范圍
碼:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.