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?
Related
i have external controller (for e.g. ExtController ) in another assembly ( folder config/extensions ).
Registration:
builder.RegisterControllers(assembly).Named<IController>(t =>
t.Name.Replace("Controller", string.Empty)
);
Getting a controller ( i have own controller factory ):
public override IController CreateController
(System.Web.Routing.RequestContext requestContext, string controllerName)
{
try
{
var ctrl = _base.CreateController(requestContext, controllerName);
return ctrl;
}
catch (HttpException htte)
{
Object ic = null;
if (_container.TryResolveNamed(controllerName, typeof(IController), out ic))
{
return ic as IController;
}
else
throw htte;
}
}
And if i doing request for this controller i get "root" autofac lifetime scope.
In other controllers i got "AutofacWebrequest" scope.
Could you help me ? Maybe is another way for controller creation from another assembly ?
Edit
I resolved my problem but i think is not the best way i can do it.
I changed from:
if (_container.TryResolveNamed(controllerName, typeof(IController), out ic))
to:
if ( (DependencyResolver.Current as Autofac.Integration.Mvc.AutofacDependencyResolver).RequestLifetimeScope.TryResolveNamed(controllerName, typeof(IController), out ic))
Unfortunately, if your integration point is a custom controller factory working against named services, you are probably stuck with what you have. You can use AutofacDependencyResolver.Current rather than casting DependencyResolver.Current yourself, but the principle will still be the same.
However, I did notice you didn't show what the base ControllerFactory is. It appears you have a sort of decorator pattern going with _base being called rather than base (without the underscore). The DefaultControllerFactory already runs controller instantiation through the dependency resolver. Of course, that would mean you need to not register controllers as named services and instead just register them with the standard RegisterControllers method.
Again, if you have to register them named (for whatever reason) and/or if the base call to CreateController isn't going through the standard DefaultControllerFactory, then what you have is correct. If you can stop registering controllers as named services, though, the standard dependency resolution pipeline will "just work" and you won't need all the extra code.
There is detailed documentation on Autofac MVC integration on the Autofac doc site.
I've taken this approach to injecting a custom resource provider in my ASP.NET MVC application, but I'm having some problems with object lifetime management.
I'm using Castle Windsor, so I have the following implementation of the factory:
public class DefaultResourceProviderFactory : ResourceProviderFactory
{
public override IResourceProvider CreateGlobalResourceProvider(string classKey)
{
// IoC is a static helper class that gives me static access to the
// container. IoC.Resolve<T>(args...) simply calls container.Resolve<T>(args...).
return IoC.Resolve<IResourceProvider>(new { resourceType = "Global" });
}
public override IResourceProvider CreateLocalResourceProvider(string virtualPath)
{
// resourceType
return IoC.Resolve<IResourceProvider>(new { ResourceType = virtualPath });
}
}
However, the IResourceProvider I have registered in the container doesn't seem to have its lifetime managed correctly. It has some other dependencies of its own, some of which have somewhat complicated lifestyles (per web request or per transaction), so I've registered the IResourceProvider as transient to ensure that its dependencies are always valid. But the MVC framework is stepping on my toes, keeping a reference to the IResourceProvider across web requests, which causes ObjectDisposedExceptions when its dependencies have been invalidated on the next request.
What I'd like to do, is to make the MVC framework use the factory every time it needs an instance of my IResourceProvider, and - if possible - also to invoke IoC.Release(provider) or something similar when it's done with it.
How do I micro-manage the lifestyle of the custom IResourceProvider in a way that the MVC framework will respect?
After searching around for various ways to control the lifetime of the IResourceProvider itself, I decided that it was better to refactor my implementation to utilize the Typed Factory Facility.
My IResourceProvider implementation formerly looked something like this:
public class CachedResourceProvider : IResourceProvider {
CachedResourceProvider(IResourceRecordRepository repo) { /* ... */ }
// other members...
}
Now, I changed it to this instead:
public class CachedResourceProvider : IResourceProvider {
CachedResourceProvider(IResourceRecordRepositoryFactory repo) { /* ... */ }
// other members...
}
The factory interface is a new one, defined as
public interface IResourceRecordRepositoryFactory {
IResourceRecord NewInstance();
void Release(IResourceRecord instance);
}
and every usage of the private _repo instance in the CachedResourceProvider was refactored to three statements: get a repo instance from the factory, use the repo instance to fetch/save something, release the instance through the factory.
I registered them like this:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IResourceRecordRepositoryFactory>().AsFactory());
Now, even though MVC is keeping a reference to my resource provider across web requests, the services it uses are re-fetched from the Windsor container each time they're used, so the container is in full control of their lifetime.
I am using Simple Injector as my IoC container and employ the following technique to enable registering a "mixed" lifestyle for some objects as both per web request or per thread.
interface IUnitOfWork { }
interface IWebUnitOfWork : IUnitOfWork { }
interface IThreadUnitOfWork : IUnitOfWork { }
class UnitOfWork : IWebUnitOfWork, IThreadUnitOfWork { }
container.RegisterPerWebRequest<IWebUnitOfWork, UnitOfWork>();
container.RegisterLifetimeScope<IThreadUnitOfWork, UnitOfWork>();
container.Register<IUnitOfWork>(() => container.GetInstance<UnitOfWork>());
// Register as hybrid PerWebRequest / PerLifetimeScope.
container.Register<UnitOfWork>(() =>
{
if (HttpContext.Current != null)
return container.GetInstance<IWebUnitOfWork>() as UnitOfWork;
else
return container.GetInstance<IThreadUnitOfWork>() as UnitOfWork;
});
I am not entirely satisfied with this solution as for each requirement I must define extra empty interfaces to make it work and ensure they are referenced by my concrete class.
Is there any reason I should not use the following extension methods instead of defining the extra interfaces? If there is some issue with these methods is there some other way to establish, with complete confidence, that my current instance of the container is running within IIS?
public static void RegisterHybridLifestyle<TService, TImplementation>(
this Container container)
where TService : class
where TImplementation : class, TService
{
if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TService, TImplementation>();
else
container.RegisterLifetimeScope<TService, TImplementation>();
}
public static void RegisterForLifestyle<TConcrete>(
this Container container)
where TConcrete : class
{
if (HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TConcrete>();
else
container.RegisterLifetimeScope<TConcrete>();
}
UPDATE
The above question and this follow on question were based on a misunderstanding of SimpleInjector and hybrid registration. The techniques described above and elsewhere on SO are for when the container can be servicing request for both Web Requests and for background processes that are not running within the context of a web request. What I have been trying to achieve is variable registration to cater for a configuration of the container that is suitable for both Web Request OR Thread Request. i.e. I need to configure my container to work within IIS and to work within a windows service. I don't need the dynamic registration that can cater for both a the same time.
The outcome of this is the following extension methods and I have removed the "extra" interfaces from my solution :-)
public static void RegisterForScope<TService, TImplementation>(this Container container)
where TService : class
where TImplementation : class, TService
{
if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TService, TImplementation>();
else
container.RegisterLifetimeScope<TService, TImplementation>();
}
public static void RegisterForScope<TConcrete>(this Container container)
where TConcrete : class
{
if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
container.RegisterPerWebRequest<TConcrete>();
else
container.RegisterLifetimeScope<TConcrete>();
}
I am not entirely satisfied with this solution
Yes, I agree with this. To be honest, having to do things like this actually sucks IMO. That's why this is fixed in Simple Injector 2.0. It contains the explicit notion of lifestyle and it will contain a Lifestyle.CreateHybrid method, that makes it much easier to register hybrid lifestyles.
You however, don't seem to need a hybrid lifestyle add all. A hybrid lifestyle is a lifestyle that can switch dynamically (on each call to GetInstance<T> and per each injection), while you only seem to need to switch during start-up. I see no harm in using the RegisterHybridLifestyle extension method as you defined it, but keep in mind that this is not really an hybrid lifestyle (so the name is a bit misleading), but simply a configuration/deployment-switch.
Simple Injector 2 and up make this much easier, and it will allow you to do something like this:
// Define a lifestyle once based on the deployment.
Container.Options.DefaultScopedLifestyle =
Lifestyle.CreateHybrid(
lifestyleSelector: HostingEnvironment.ApplicationHost != null,
trueLifestyle: new WebRequestLifestyle(),
falseLifestyle: new LifetimeScopeLifestyle());
// And use it for registering the unit of work
// (no extra interfaces needed anymore).
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
// After setting DefaultScopedLifestyle, you can usr Lifestyle.Scoped
container.RegisterCollection(
typeof(ISubscriber<>),
new [] { typeof(ISubscriber<>).Assembly },
Lifestyle.Scoped);
I'm building an ASP .Net MVC 2 application and I want to follow the ideas from Mark Seemann's book "Dependency Injection in .Net" so I registered my custom Controller Factory in the Global.asax file and I'm configuring the container within the Controller Factory like so:
public IController CreateController(RequestContext context, Type controllerType)
{
var container = new Container();
object controller;
if(controllerType == typeof(MyControllerOne)
{
container.Configure(r => r.
For<IService>().
Use<ServiceOne>());
}
else if(controllerType == typeof(MyControllerTwo)
{
container.Configure(r => r.
For<IService>().
Use<ServiceTwo>());
}
......
return container.GetInstance(controllerType) as IController;
}
Now this code works (though it is possible I may have a mistake somewhere since I'm writing this by memory), the dependencies are being resolved and the correct controller is being instantiated with the correct dependency every time, but it seems that for every request the container is being configured to resolve the dependencies that will be needed at that moment. So my questions are:
Isn't that redundant?
Shouldn't the configuration of the container be done in the Global.asax as well so it is only done once? If so, how could this be done?
By configuring the container the way I'm doing it, how will object lifetime be affected? I mean, eventually there will be repositories that should have a singleton lifetime, some others should be created once by HTTP request, and so for. What could be the implications?
Any comments, ideas and/or suggestions will be much appreciated.
By the way, the IoC container I'm using is StructureMap though I think that for this particular question it might not be too relevant.
It is, indeed, redundant to conditionally register each controller upon request. With StructureMap, the Controller Factory should look like this:
public class StructureMapControllerFactory : DefaultControllerFactory
{
private readonly IContainer container;
public StructureMapControllerFactory(IContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
protected override IController GetControllerInstance(
RequestContext requestContext, Type controllerType)
{
return (IController)this.container.GetInstance(controllerType);
}
}
All services should be unconditionally registered in a single container instance. As an example, you can register all Controllers with StructureMap like this:
this.Scan(x =>
{
x.AssemblyContainingType<HomeController>();
x.AddAllTypesOf<IController>();
x.Include(t => typeof(IController).IsAssignableFrom(t));
});
This is basically just following the Register Resolve Release pattern.
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.