I'm trying to have a better understanding of the lifetime of objects in DI by the point of view of an webapp. I'm using Unity Container docs here.
Singleton
Singleton lifetime creates globally unique singleton. Any Unity
container tree (parent and all the children) is guaranteed to have
only one global singleton for the registered type.
Now, because I've read so many articles, I've come to understand that Singleton is a instance that is created once and used for the entire life of application. What does this mean having in mind that 2 users use my app in the same time(or not) from different PCs - does this mean that if this instance is a variable, it will be common for all users for the entire time my app is hosted on the server (or until app App Pool Recycle)?
In my app I use different services that are injected in the controllers constructor.
Will Singleton be suited for an instance of a log service, or a DbContext instance?
If I use it for a DbContext instance, and something get's modified in the my Db structure - this instance will update?
Per Container
Per Container lifetime allows a registration of an existing or
resolved object as a scoped singleton in the container it was created
or registered. In other words this instance is unique within the
container it was registered with. Child or parent containers could
have their own instances registered for the same contract.
Same case: If 2 users use my app in the same time and visit same Controller, does this mean that they share the same instance of a Per Container variable/service?
Hope these questions have some meaning and I don't simply overthink it. Thank you!
Related
Imagine you inject a single database connection to a handful of service classes. They now share what's essentially a global mutable state. How do DI frameworks deal with this? Do they:
Freeze the dependency before injection?
Only share immutable objects?
Wrap each dependency in a decorator to only provide exactly what's dependent on?
I tried searching for this and am a bit surprised I didn't find much. Feel free to provide links.
Related: https://en.wikipedia.org/wiki/Principle_of_least_privilege
Most DI containers provide the feature of registering a dependency within a Lifetime. For instance in .net core DI you can register a service with three different lifetimes:
Singleton: There is only one single instance. All the consumers of that service will use that instance. If one consumer changes the state of that dependency, all the other consumers will see that change.
Scoped: There is one instance per scope, where a scope is a web request. If a consumer changes the state of a scoped service, all the other consumers that will run in the same web request will see the change.
Transient: Each consumer uses a different instance of the service.
Always in .net core, the DBContext is (by default) added as a scoped service, this means that in the same web request all the consumers will use the same instance and this is useful when you need to run a transaction across different consumers (or better across different repositories).
I followed this links. https://dontcodetired.com/blog/post/Azure-Functions-Dependency-Injection-with-Autofac
Autofac Binding at Runtime
It worked fine. I want to know when azure function scales, object injected into azure function will be shared by all the instances of azure function. In this case object is NaiveInvestmentAllocator.
Let me know if you have any doubt. Also I actually implemented combination of two links. It is like factory pattern is used to get the object of instances from Autofac container. I can share the code if anyone want But I dont think that necessary.
My question is if I implemented first link, injected object is shared by all instances of same azure function or not?
Nope.
As Azure Functions scale, the other instances run on different VMs/Containers. Its similar to running your function app on different VMs/Containers manually.
If the requirement is to have a shared state across multiple function app instances, you should offload the state persistence to something like Redis, Table Storage, Blob Storage, etc.
For example, you can use Azure Cache for Redis for example and inject a client for the same into your service class.
If the intention is to save the number of open connections, note that the limit is per instance.
OK, I wired up StructureMap to my Web Api application (plenty of samples how to do this here on StackOverflow and elsewhere on the Internet). My understanding of object lifetime maintenance in Web Api is that it's done via nested containers.
For the whole idea of object lifetime maintenance via nested containers to work, Raven's session object would have to be created in child container as a transient singleton. Right now I have IDocumentStore defined in in parent container and scoped as singleton. IDocumentSession is also defined in parent container but scoped as HttpContext. When request comes in, BeginScope() is called, nested container is created but IDocumentSession object in it is inherited from the parent instead of being created.
I don't understand how this is supposed to work. If object is not created in child container as a transient singleton but is inherited from the parent instead then it will go back to the parent when nested container is disposed. This then defeats the whole idea. If on the other hand session is to be created in nested container as a transient singleton then how this can be accomplished? How can I verify the correctness of such setup?
If I set IDocumentSession as Per Web Request then why the need for
nested containers in the first place?
There is no need for nested containers in that scenario.
The need for nested containers by itself in general is even doubtful. Even the designer of Castle Windsor (a container that supports child containers) is considering to remove support for child containers in the next version of Castle Windsor all together.
Can I assert rails/sinatra apps are initialized only once and all requests share the same app
instance? or do new requests spawn new app instances?
Is it possible to instance custom classes and persist them during app lifetime without using sessions, database storages or third party services? If so, what are the implications from a thread-safeness point of view?
I'm trying to figure how to implement a web-based download manager and I'm currently evaluating ruby-based frameworks.
Can I assert rails/sinatra apps are
initialized only once and all requests
share the same app instance? or do new
requests spawn new app instances?
Not generally. This really depends on your setup. If you only run on process with a server (aka Rack handler) that reuses the same application object, this will work. Whether the same instance of your application is used depends on the web framework you are using. Sinatra for instance creates a new instance of your application class (usually Sinatra::Application) for every request if used as Rack endpoint.
Is it possible to instance custom
classes and persist them during app
lifetime without using sessions,
database storages or third party
services? If so, what are the
implications from a thread-safeness
point of view?
If you really want to persist classes, you will probably need something like maglev. However, I believe you mean persisting instances of custom classes. If you don't want to use a database for persistence (you really should), you could fall back to PStore, which ships with Ruby.
My controllers now implement an interface and inject a repository implementation using the Unity framework. My question is, are these injected implementations singletons? Does that mean all of my users hitting the repository (from the controller) use the same instance?
It depends on whether you carry some ORM session along with your repository instance. If your repository is just a bunch of static methods than you shouldn't care and you can make it a singleton. Otherwise you want to preserve the state only within one web request so that other requests threads don't interfere with it.
Unity, unlike other IoC frameworks. doesn't come with singleton per web request lifetime manager, but you can easily implement it, see here for instance:
Singleton Per Call Context (Web Request) in Unity
No, do not make repositories singleton, special in a web application.
The controller factory create the repository (using Unity) and inject them in the controller.
Taken from the MSDN Unity docs...
The lifetime of the object it builds will correspond to the lifetime you specify in the parameters of the method. If you do not specify a value for the lifetime, the type is registered for a transient lifetime, which means that a new instance will be created on each call to Resolve...
Include an instance of the ContainerControlledLifetimeManager class in the parameters to the RegisterType method to instruct the container to register a singleton mapping.
So basically, the injection is transient unless you specify it as a singleton.