Does Resolve<T>() return objects per-session? - c#

In Microsoft Unity IoC, if I call Resolve<SomeType>(), can I guarantee that the object returned is the one that was created during the current session?
For example, three users sign on, and let's say that the object of SomeType that gets created in the container has different values for each user. Will a call to Resolve return the object that was created for the current user? Or would it do something stupid like return the last one that was created?
I'm having troubles testing this myself due to some environment problems and I need to check something in soon, so if someone could answer this it would be very helpful!
Edit
Forgive me for I am very new to Unity, but based on what I read here, it seems like I should be able to register objects in the container with a unique name and retrieve them by that name. So, wouldn't I be able to use a session ID or some other value that persists within a session to retrieve my object?

Oh wow, lifetime management using Unity in am MVC app. Where do I start?
First of all, session singletons are not really possible as there is no ASP.NET system that will guarantee that the same instance will be used between requests in the same session. The session can mimic the same object persisted within the session by serializing and deserializing it between requests.
Transient instances - i.e. simple registrations without lifetime management specification are sufficient 99% of the time. This implies that an instance of registered type will be created every time it is needed.
It is very rarely that you need instances to live throughout the lifetime of the request. However when you need those, you really need those. A connection to a DB is a perfect candidate for this. Request singletons, on the other hand are much easier to create and manage.
The most elegant solution is to use Unity's child container feature. A child container can be created at the beginning of the request, disposed at the end of the request (as an added bonus it will dispose all ContainerControlledLifetimeManager instances).
When creating a child container, all registrations are still available from the parent container, so you need to register request specific stuff with the child container.
Here is pseudo-code to get this working:
private void Application_Start() {
_parentContainer = new UnityContainer();
//creates a transient registration, available at any point in the app.
_parentContainer.RegisterType<IParentIntf, ParentIntfImpl>();
ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory());
}
private void Application_BeginRequest() {
var childContainer = _parentContainer.CreateChildContainer();
//registers a request "singleton"
//This registration is a type registration, an instance of RequestInterfaceImpl
//will be created when needed and then kept in the container for later use.
childContainer.RegisterType<IRequestInterface,RequestInterfaceImpl>(new ContainerControlledLifetimeManager());
//save the child container in the context, so we can use it later
HttpContext.Items["childContainer"] = childContainer;
}
private void Application_EndRequest() {
//dispose the child container
((IUnityContainer)HttpContext.Items["childContainer"]).Dispose();
}
One other thing that needs to be done is to override the Controller Factory to use the child container to create controllers. Controller are the first point of entry into the application and they could simply take a dependency on other components in their constructor.
public class UnityControllerFactory : DefaultControllerFactory {
#region IControllerFactory Members
public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
IController controller;
controllerName = controllerName.ToLower();
var container = ((IUnityContainer)HttpContext.Items["childContainer"])
if(container.IsRegistered<IController>(controllerName))
controller = container.Resolve<IController>(controllerName);
else
controller = base.CreateController(requestContext, controllerName) ;
return controller;
}
}

The default behaviour will be to return a new instance for each resolve call, this isn't what you want.
It would be possible to create and resolve the same instance within a session, but there is no built in support as far as I know. You would have to write your own lifetime manager, and then use this when registering your type.
There is a lifetime manager that can do per thread instances, but this isn't useful for sessions as threads will get re-used, and resolve would need to also work across multiple requests to be truly session-scoped.
It's entirely possible that someone has written a lifetime manager for this.

Related

C# Autofac New Instance

I have a class "DependencyResolver" where I return instances of objects by hand. There I used "Activator.CreateInstance".
I wanted to change it so it uses autofac.
My function "Get" works fine:
public T Get<T>()
{
return _container.Resolve<T>();
}
But I also have a function "CreateNew" where I need a new instance:
public T CreateNew<T>()
{
return _container.Resolve<T>();
}
The Problem is that I always get the same instance.
My Registration looks like this:
var builder = new ContainerBuilder();
foreach (var dllFileName in DependencyMapping.GetAllDllFilenames())
{
builder
.RegisterAssemblyTypes(Assembly.LoadFile(Path.Combine(GetPathFromInstalledSys(), dllFileName)))
.AsImplementedInterfaces()
.SingleInstance();
}
_container = builder.Build();
So there is a place where I can control the behaviour: "SingleInstance" or "InstancePerDependency". But I dont know whether the user needs a new instance or not. Is there any way to change the behavior when "CreateNew" is called?
Lifetime scope (single instance, instance per dependency) is controlled at registration time, not resolve time. There's no way to change it. This is the case with all DI containers, not just Autofac. Part of the point of it is that the consumer shouldn't have to know what scope they want - they just ask for a thing and get it.
Consumers also generally shouldn't deal with disposal - things get disposed by the container.
Note what you have here is service location (client asks the container for a thing), not dependency injection (client takes dependencies in constructor and doesn't know about the container). While service location is sometimes required, generally try to avoid it if you can; it's not really much better than just calling new in your code.

ASP.NET Core Replacing a Singleton Instance at Runtime

I need to keep an object in memory for the lifetime of the ASP.NET Core application in which I serialize this object and store it in durable storage as a snapshot. Later on in the life-cycle of the object I need to restore the state of this object by de-serializing it and replacing the singleton. It doesn't have to be a singleton but I need to guarantee that there's only a single instance of the object.
I tried the following but it seems it only replaces it for the current request and nothing after that. I assume the DI container makes it's own copy of the object but I'm not sure
internal static SingleObject SingleObject { get; set; } = new SingleObject();
services.AddSingleton<OrderBook>(SingleObject)
Is there a way to replace the singleton instance or will I have to roll my own singleton class that handles this scenario?
I would invite you to read How to configure services based on request in ASP.NET Core.
After that (container being built), the registrations can't be changed
anymore. #Tseng
You can only register scopes once during startup, so you could register functions related to what you want to update/refresh later on. I would recommend if you have something that needs to change implementing a cache or in memory storage that you trigger a refresh when desired.
I had a singleton of CachedData until realized needed to fast reset it at some point. So just implemented a wrapper (see below). Now the wrapper ResettableCachedData is singleton, and CachedData is transient. At any time a can do a quick Reset() to recreate CachedData, while accessing it's data via ResettableCachedData.Data.
public class ResettableCachedData
{
private readonly IServiceProvider _services;
public ResettableCachedData(IServiceProvider services)
{
_services = services;
Reset();
}
public CachedData Data { get; protected set; }
public void Reset()
{
Data = _services.GetRequiredService<CachedData>();
}
}
From https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2:
Singleton
Singleton lifetime services are created the first time they're requested (or when ConfigureServices is run and an instance is specified with the service registration). Every subsequent request uses the same instance. If the app requires singleton behavior, allowing the service container to manage the service's lifetime is recommended. Don't implement the singleton design pattern and provide user code to manage the object's lifetime in the class.
So, you don't need to implement the Singleton pattern your self. The DI takes care of that.
The only thing you should do now is injecting it.
Register as follow:
services.AddSingleton<SingleObject>(new SingleObject())

Windsor container. Lifetime of objects in ASP.NET MVC application

I have a new project where Windsor container is used for IoC.
Here is simplified code executed in Install
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<BaseController>().LifestyleTransient(),
Component.For<ISecurityManager>().ImplementedBy<SecurityManager>(),
Component.For<IAccountManager>().ImplementedBy<AccountManager>()
........)
}
Information that I found in official documenation is not enough for understand in detail these lines.
Classes.FromThisAssembly().BasedOn<BaseController>().LifestyleTransient(),
This line in Register method enables dependency injection to all classes in my application that are inherited from BaseController.
BaseController is included.
Injection will not be made to other classes than described above.
We show to container that lifetime of all controllers classes will be an instance.
Component.For<ISecurityManager>().ImplementedBy<SecurityManager>()
To all controllers registered above, if they have in constructor interface ISecurityManager will be injected instance of class SecurityManager.
Lifetime of this SecurityManager is singleton as default value. So after application start we will have only one instance of SecurityManager for all controllers till the end of application execution.
Are my ideas correct? It seems that not, at least because LifestyleTransient() for controllers seems to me strange and that injected objects will be singletons too.
From bottom to the top :
Lifetime of this SecurityManager is singleton as default value. So after application start we will have only one instance of SecurityManager for all controllers till the end of application execution.
Exactly this is going to happen.
It seems that not, at least because LifestyleTransient() for controllers seems to me strange and that injected objects will be singletons too.
Controllers are transient because they hold the HttpContext - they have the information about the current user request and the following response. This is why they are transients and not singletons - the HttpContext is per request and it is created every time a browser/client requests something.
So it is understandable why controllers have shorter lifespan than your other services. It greatly depends on the inner architecture of the application. If someone else has a better idea why - I am more than willing to learn.
The Register/Resolve/Release cycle of your controllers can be done by creating a custom controller factory and substituting the default :
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
if (_kernel.GetHandler(controllerType) != null)
{
return (IController)_kernel.Resolve(controllerType);
}
return base.GetControllerInstance(requestContext, controllerType);
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
}
and somewhere put :
container.Register(Component.For<IControllerFactory>().ImplementedBy<WindsorControllerFactory>());
My controllers too have singleton dependenices. In this way you can achieve a pipeline programming model - you funnel the request from the controller through a series of objects and than return the results.
If SecurityManager has something to do with Authentication or Authorization it maybe better to use the MVC default Filtering mechanisms like IAuthorizationFilter or AuthorizeAttribute. Of course this maybe data access filter and it may be reasonable to put it in a different object.
Did I answer your questions?

Nancy IoC per request auto registration

We have an ASP.NET REST service implemented with Nancy (and TinyIoc), which interfaces with a quite large legacy application. We would like to transition to full dependency injection. At the moment most of our modules instantiate the controllers directly, and takes a context class which holds the request information using the NancyContext Context property. Something like this:
public FooModule(ILegacyService legacyService) {
Get["/"] = parameters => new FooController(new RequestContext(Context), legacyService).GetFoo();
}
We would like to inject the controllers directly in the module, and get everything handled by the super-duper-happy-path :)
Our problems all stem from the fact that we need information from NancyContext. The url, headers etc. So we have attempted various approaches to get to dependency injection nirvana.
Attempting to inject controllers failed, since they're instantiated in application scope, and so any dependency to RequestContext would not have the current context information. Even registering RequestContext in ConfigureRequestContainer did not ripple through to all dependants, and they would hold references to an out of date RequestContext.
We have tried to property inject the context using IRequestStartup, and this seemed successful, until we ran into concurrency issues. Simultaneous requests in different threads would overwrite the application scope RequestContext.
We found out that we could call container.AutoRegister() in ConfigureRequestContainer, but this resulted in severe lag, since registrations takes seconds with the amount of types we have.
Using AsPerRequestSingleton() in ConfigureApplicationContainer seems like it will register once, and then instantiate per request, but there doesn't seem to be a way to get auto registration to adhere to this.
It seems like we need to register all types manually, and keep this configuration up to date manually. Is this the case? We really would prefer to have some type of auto registration with per request lifetime.
I have created a small test project (https://github.com/Rassi/NancyIocTest) in which I attempted some of these solutions.
Using DefaultNancyAspNetBootstrapper you can create your own auto registering like this:
public class Bootstrapper : DefaultNancyAspNetBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
var assemblyClasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsClass);
foreach (var assemblyClass in assemblyClasses)
{
var interfaces = assemblyClass.GetInterfaces();
if (interfaces.Count() == 1)
{
container.Register(interfaces[0], assemblyClass).AsPerRequestSingleton();
}
}
}
Everything is then instantiated per request, and you can inject context information using RequestStartup():
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
var requestUrl = container.Resolve<IRequestUrl>();
requestUrl.Context = context;
}
}
This is a simple proof of concept, which will find classes which implement one interface, and register it to that. A couple of issues should probably be handled, such as: Registering classes implementing multiple interfaces (perhaps using the convention of registering Name to IName). And also handling multiple classes registering the same interface.

Reason to use PerThreadLifetimemanager vs Transientlifetimemanager

I use DI in constructors.
BaseShoppingCart is a service in which I set ShoppingCartId (used for cart items).
here is the constructor:
public BaseShoppingCart( HttpContextBase context, IRepository<TCart> cart ,IProductService productservice)
{
_context = context;
_cart = cart;
_productService = productservice;
ShoppingCartId = _context.Request.IsAuthenticated ? _context.User.Identity.Name : getSessionCartId();
}
If I set Transientlifetimemanager (by default) in DI container (Unity) no bugs are revealed.
If I set PerThreadLifetimeManager any user may get cart of another user! As I read from this article Why is PerThreadLifetimeManager used in this example? - thread is longer than request so second call of ShoppingCartController is this case may not invoke ctor of BaseShoppingCart. Instead existing BaseShoppingCart object (object of another user) is returned from container.
I need your opinions:
Do I understand this problem correcltly?
In which cases PerThreadLifetimemanager is useful insted of Transientlifetimemanager?
Thanks!
To isolate users (requests) create new child container per request and resolve services from child one. So, you can register your services with HierarchicalLifetimeManager and you'll get new instance for each user (request).
Here are good examples.
And I don't recommend to use PerThreadLifetimeManager if you don't know, what you actualy do.

Categories