This project is read-only.

Inject request-scoped object into application-scoped object

May 20, 2014 at 5:39 PM
Is it possible to inject a request-scoped object into an application-scoped object? For example, inject a "unit of work" object repeatedly into an OAuthAuthorizationServerProvider upon every request.
May 20, 2014 at 6:52 PM
With dependency injection, the practice is that you store the dependencies of a component as private fields. This is in the majority of cases the best solution. This does mean however that the component holds on to its dependencies for as long at it lives. Because of this reason, in general, you should prevent letting a component depend on a service that is registered with a shorter lifestyle. Because these types of configuration errors are very common, and sometimes hard to detect manually, the Simple Injector Diagnostic Services warn for this type of misconfiguration.

Sometimes however, you're dealing with integration scenarios where you don't control the lifestyle of the used object. A good example of this are global action filters in ASP.NET MVC. An IActionFilter that is registered in the global action filter list lives for the duration of the entire application an can therefore be considered to be a Singleton. If such a service however contains any dependencies on its own, those dependencies should be singleton as well; otherwise your application might start to behave incorrectly.

There are a few ways around this. In the case that the component in question needs to be in control of the lifetime of one of its dependencies, the general solution is to inject a factory instead. Example:
public class MyActionFilter : IActionFilter
{
    private readonly IUnitOfWorkFactory uowFactory;

    public MyActionFilter(IUnitOfWorkFactory uowFactory) {
        this.uowFactory = uowFactory;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext) {
        using (var uow = this.uowFactory.Create()) {
            // do something useful with the UoW.
        }
    }
}
Alternatively, you can go with the short-cut version of this pattern and replace the IUnitOfWorkFactory interface with a Func<T> delegate as explained here.

Another approach however is to create a proxy class that will control the lifetime and let the real component have the proper lifetime
// Simply inject the UoW in the real component; not the factory.
public class MyActionFilter : IActionFilter
{
    private readonly IUnitOfWork uow;

    public MyActionFilter(IUnitOfWork uow) {
        this.uow = uow;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext) {
        // do something useful with the UoW.
    }
}

// Define a proxy that can control the lifetime of the real component
public class SimpleInjectorActionFilterProxy<TFilter> : IActionFilter
    where TFilter : IActionFilter
{
    private readonly Container container;

    public SimpleInjectorActionFilterProxy(Container container) {
        this.container = container;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext) {
        // Always resolve a new instance on each call.
        var filter = this.container.GetInstance<TFilter>();
        filter.OnActionExecuting(filterContext);
    }
}
This proxy will always call back to the container on each call to OnActionExecuting to get the specified component. This allows the component to be registered with the correct lifestyle and allows the system to work as expected.

The proxy class now can be registered as global filter in the following way:
GlobalFilters.Filters.Add(new SimpleInjectorActionFilterProxy<MyActionFilter>(container));
Which of these solutions is best in your case depends on the shape of the interfaces you're working with and how integration needs to be done. I hope this gives you some ideas.
May 21, 2014 at 3:30 AM
Edited May 21, 2014 at 3:32 AM
The UnitOfWork object is a shared resource. It is also injected into apiControllers. Since apiController is also request-scoped, it is perfect to accept a container-created request-scoped UnitOfWork instance through constructor injection. This makes the factory approach invalid, because I cannot let the factory create another instance of UnitOfWork.

The proxy approach is equivalent to inject the container itself into an application-scoped object, and query the container to get UnitOfWork instance. This is the approach I am currently using. I don't like this approach because it transfers dependency from UnitOfWork to container, not a clean removal of dependency. Maybe this is the only way any DI framework can do.

I am not familiar how DI works under the hood. Is it possible to register a property in such a way that the container refresh or reset it whenever a new instance is created?
May 21, 2014 at 6:56 AM
It doesn't make the factory approach invalid per see, but in that case you should not let the consumer dispose it. A simple thing you can have is the following registration:
container.RegisterWebApiRequest<IUnitOfWork, MyUnitOfWork>();
container.RegisterSingle<Func<IUnitOfWork>>(() => container.GetInstance<IUnitOfWork>());
This allows you to inject your component with a Func<IUnitOfWork> and every time you call the delegate from within your component, you will get an IUnitOfWork instance that is request-scoped.

>> I am not familiar how DI works under the hood

There's not much magic under the hood with DI containers. They just return some implementation based on the abstraction you ask for and they might cache that instance to be able to return the same instance later on. You should always wonder how you would do things when wiring it by hand, without a DI container. The Dependency Injection pattern is applicable, even without a DI framework.

>> Is it possible to register a property in such a way that the container refresh or reset it whenever a new instance is created?

Yes, this is possible, but this isn't any different from a constructor-injected dependency. If you need this, you will have to either use a Func<T> delegate or create a proxy class. In theory, a DI container could generate this proxy for you, but none of the DI containers for .NET magically do this for you, since that would bring more harm than good. I would say that hand-writing those few proxies you need is your best option. If you need many proxies, you might want to take a step back and look at your design.
Marked as answer by dingjing on 5/21/2014 at 11:44 AM
May 21, 2014 at 12:17 PM
RegisterSingle<Func<>>() is a brilliant idea! This is functional programming at its best.