Graham Graham - 3 months ago 31
C# Question

With lifestyle to use for Console Application?

I have a unit of work class which is registered with Simple Injector in a common assembly that is shared by various web apps.

It is registered as:

Container.Register(typeof(IUnitOfWork), typeof(UnitOfWork), new WebRequestLifestyle());


I now have a console application that needs to use the container defined in the assembly, but obviously cannot use
WebRequestLifestyle
. I get the following error if I try:


The
IUnitOfWork
is registered as 'Web Request' lifestyle, but the instance is requested outside the context of a Web Request.


Is there an alternative I can use to
WebRequestLifestyle
that will achieve the same functionality but for both web and console applications?

Answer

Is there an alternative I can use to WebRequestLifestyle that will achieve the same functionality but for both web and console applications?

Yes there is. In Simple Injector v3 the adviced pattern is to always use Lifestyle.Scoped:

Container.Register(typeof(IUnitOfWork), typeof(UnitOfWork), Lifestyle.Scoped);

Lifestyle.Scoped is a 'placeholder lifestyle' that maps to the scoped lifestyle configured through Container.Options.DefaultScopedLifestyle.

This means that in your web application you will have to create a new Container instance using:

var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

This makes the rest of your configuration oblivious to the given end application.

In your console application, you should typically use the LifetimeScopeLifestyle. This means the creation of your container will look as follows in your console application:

var container = new Container();
// Use the SimpleInjector.Extensions.LifetimeScoping NuGet package for this
container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle();

The LifetimeScopeLifestyle is a thread-dependent lifestyle and requires explicit management. This means you will have to manually start and dispose a lifetime scope before and after an operation. If your console application is short-lived, this will typically mean you do this in the main method:

void Main() 
{
    var container = BuildContainer();

    using (container.BeginLifetimeScope())
    {
        var service = container.GetInstance<MyRootType>();

        service.DoSomething();
    }

    container.Dispose();
}

In case the console application is long(er) running, it will probably handle multiple autonomous requests (much like individual web requests). In that case you will have to wrap each individual request with a lifetime scope (much like the example above).