rraszewski
rraszewski

Reputation: 1145

Autofac instance per viewmodel

I have a little problem with Autofac configuration. My goal is to create new EFContext per ViewModel

Right now I have:

ContainerBuilder builder = new ContainerBuilder();

builder.Register(ctx => new EFContext())
            .InstancePerLifetimeScope();

builder.Register<FirstService>(c => new FirstService(c.Resolve<EFContext>()));
builder.Register<SecondService>(c => new SecondService(c.Resolve<EFContext>()));
builder.Register<OtherService>(c => new OtherService(c.Resolve<EFContext>()));

builder.Register<FirstViewModel>(c => 
            new FirstViewModel(
                c.Resolve<FirstService>(), 
                c.Resolve<SecondService>(), 
                c.Resolve<OtherService>()
            ));
builder.Register<SecondViewModel>(c => 
            new SecondViewModel(
                c.Resolve<FirstService>(), 
                c.Resolve<SecondService>(), 
                c.Resolve<OtherService>()
            ));

But now when I create SecondViewModel all services get the same EFContext as in FirstViewModel services

Upvotes: 2

Views: 1366

Answers (2)

Sjeijoet
Sjeijoet

Reputation: 741

I've made another attempt, and I think this is currently the best solution I can find.

Could you try and see if the following works for you (from the Autofac Documentation)?

//First builder
ContainerBuilder builder = new ContainerBuilder();

//Register context as Lifetime dependent.
builder.Register(ctx => new EFContext())
            .InstancePerLifetimeScope();

//Register services.
builder.Register<FirstService>(c => new FirstService(c.Resolve<EFContext>()));
builder.Register<SecondService>(c => new SecondService(c.Resolve<EFContext>()));
builder.Register<OtherService>(c => new OtherService(c.Resolve<EFContext>()));

//Build first builder to work with scopes.
var container = builder.Build();

//Create a second builder.
ContainerBuilder builder2 = new ContainerBuilder();

using (var scope = container.BeginLifetimeScope())
{
    //Create services, since lambda is executed after scope is disposed.
    var firstService = scope.Resolve<FirstService>();
    var secondService = scope.Resolve<SecondService>();
    var otherService = scope.Resolve<OtherService>();

    //Register viewmodel with second builder.
    builder2.Register<FirstViewModel>(c => new FirstViewModel(
        firstService,
        secondService,
        otherService
    ));
}

using (var scope = container.BeginLifetimeScope())
{
    //Create services, since lambda is executed after scope is disposed.
    var firstService = scope.Resolve<FirstService>();
    var secondService = scope.Resolve<SecondService>();
    var otherService = scope.Resolve<OtherService>();

    //Register viewmodel with second builder.
    builder2.Register<SecondViewModel>(c => new SecondViewModel(
        firstService,
        secondService,
        otherService
    ));
}

//Build second builder.
var container2 = builder2.Build();

//Merge registration of second builder with the first.
foreach (var registration in container2.ComponentRegistry.Registrations)
    container.ComponentRegistry.Register(registration);


//Resolve the viewmodels from the container.
var firstViewModel = container.Resolve<FirstViewModel>();
var secondViewModel = container.Resolve<SecondViewModel>();

An issue could be that the services (FirstService, SecondService and OtherService) are resolved in mid-registration of components using a LifetimeScopes, which might affect more advanced dependency structures with LifetimeScopes.

Upvotes: 2

rraszewski
rraszewski

Reputation: 1145

OK, I have my answer

There wasn't any problem with Autofac configuration but in resolving dependency. Right now I have:

ContainerBuilder builder = new ContainerBuilder();

builder.Register(ctx => new EFContext())
            .InstancePerLifetimeScope();

builder.Register<FirstService>(c => new FirstService(c.Resolve<EFContext>()));
builder.Register<SecondService>(c => new SecondService(c.Resolve<EFContext>()));
builder.Register<OtherService>(c => new OtherService(c.Resolve<EFContext>()));

builder.Register<FirstViewModel>(c => 
            new FirstViewModel(
                c.Resolve<FirstService>(), 
                c.Resolve<SecondService>(), 
                c.Resolve<OtherService>()
            ));
builder.Register<SecondViewModel>(c => 
            new SecondViewModel(
                c.Resolve<FirstService>(), 
                c.Resolve<SecondService>(), 
                c.Resolve<OtherService>()
            ));

And when I want resolve dependency I use:

using (var scope = Container.BeginLifetimeScope())
{
    var vm = scope.Resolve<FirstViewModel>();
}

Upvotes: 2

Related Questions