asp.net mvc - PerRequestLifetimeManager and Task.Factory.StartNew - Dependency Injection with Unity -



asp.net mvc - PerRequestLifetimeManager and Task.Factory.StartNew - Dependency Injection with Unity -

how manage new tasks perrequestlifetimemanager? should create container within new task?(i wouldn't alter perrequestlifetimemanager perresolvelifetimemanager/hierarchicallifetimemanager)

[httppost] public actionresult uploadfile(fileuploadviewmodel viewmodel) { var cts = new cancellationtokensource(); cancellationtoken cancellationtoken = cts.token; task.factory.startnew(() => { // _fileservice = dependencyresolver.current.getservice<ifileservice>(); _fileservice.processfile(viewmodel.filecontent); }, cancellationtoken); }

you should read this article di in multi-threaded applications. although written different di library, you'll find of info applicable concept of di in general. quote few of import parts:

dependency injection forces wire dependencies in single place in application: composition root. means there single place in application knows how services behave, whether thread-safe, , how should wired. without centralization, knowledge scattered throughout code base, making hard alter behavior of service.

in multi-threaded application, each thread should own object graph. means should typically phone call [resolve<t>()] 1 time @ origin of thread’s execution root object processing thread (or request). container build object graph root object’s dependencies. of dependencies singletons; shared between threads. other dependencies might transient; new instance created per dependency. other dependencies might thread-specific, request-specific, or other lifestyle. application code unaware of way dependencies registered , that’s way supposed be.

the advice of building new object graph @ origin of thread, holds when manually starting new (background) thread. although can pass on info other threads, should not pass on container controlled dependencies other threads. on each new thread, should inquire container 1 time again dependencies. when start passing dependencies 1 thread other, parts of code have know whether safe pass dependencies on. instance, dependencies thread-safe? might trivial analyze in situations, prevents alter dependencies other implementations, since have remember there place in code happening , need know dependencies passed on. decentralizing knowledge again, making harder reason correctness of di configuration , making easier misconfigure container in way causes concurrency problems.

so should not spin of new threads within application code itself. , should not create new container instance, since can cause sorts of performance problems; should typically have 1 container instance per application.

instead, should pull infrastructure logic composition root, allows controller's code simplified. controller code should not more this:

[httppost] public actionresult uploadfile(fileuploadviewmodel viewmodel) { _fileservice.processfile(viewmodel.filecontent); }

on other hand, don't want alter ifileservice implementation, because shouldn't concern multi-threading. instead need infrastructural logic can place in between controller , file service, without them having know this. way implementing proxy class file service , place in composition root:

private sealed class asyncfileserviceproxy : ifileservice { private readonly ilogger logger; private readonly func<ifileservice> fileservicefactory; public asyncfileserviceproxy(ilogger logger, func<ifileservice> fileservicefactory) { this.logger = logger; this.fileservicefactory = fileservicefactory; } void ifileservice.processfile(filecontent content) { // run on new thread task.factory.startnew(() => { this.backgroundthreadprocessfile(content); }); } private void backgroundthreadprocessfile(filecontent content) { // here run on different thread , // services should requested on thread. var fileservice = this.fileservicefactory.invoke(); seek { fileservice.processfile(content); } grab (exception ex) { // logging important, since run on // different thread. this.logger.log(ex); } } }

this class little peace of infrastructural logic allows processing files on background thread. thing left configure container inject our asyncfileserviceproxy instead of real file service implementation. there multiple ways this. here's example:

container.registertype<ilogger, yourlogger>(); container.registertype<realfileservice>(); container.registertype<func<ifileservice>>(() => container.resolve<realfileservice>(), new containercontrolledlifetimemanager()); container.registertype<ifileservice, asyncfileserviceproxy>();

one part missing here equation, , how deal scoped lifestyles, such per-request lifestyle. since running stuff on background thread, there no httpcontext , means need start 'scope' simulate request (since background thread own new request). knowledge unity stops. i'm familiar simple injector , simple injector solve using hybrid lifestyle (that mixes per-request lifestyle lifetime-scope lifestyle) , explicitly wrap phone call backgroundthreadprocessfile in such scope. imagine solution in unity close this, unfortunately don't have plenty knowledge of unity show how. else can comment on this, or add together reply explain how in unity.

asp.net-mvc dependency-injection inversion-of-control unity-container ioc-container

Comments

Popular posts from this blog

c# - ASP.NET MVC Sequence contains no matching element -

java - Parsing XML, skip certain tags -

rest - How to invalidate user session on inactivity in a stateless server? -