Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which lifestyle to use for Console Application?

I have an 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?

like image 251
Graham Avatar asked Aug 31 '16 11:08

Graham


Video Answer


1 Answers

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 advised 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 AsyncScopedLifestyle. This means the creation of your container will look as follows in your console application:

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

The AsyncScopedLifestyle can be used for both single threaded and asynchronous operations. It requires explicit management. This means you will have to manually start and dispose a 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 (AsyncScopedLifestyle.BeginScope(container))
    {
        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 scope (much like the example above).

For more information, see the documentation.


Edit: In case you're still using v3 in a console application, you'll need to use LifetimeScopeLifestyle from SimpleInjector.Extensions.LifetimeScoping.

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

To use it, replace the using from the example:

using (container.BeginLifetimeScope())
{
    //...
}
like image 66
Steven Avatar answered Oct 23 '22 10:10

Steven