Instance scope at resolution time

35 views
Skip to first unread message

Ilia Jerebtsov

unread,
Jul 8, 2010, 10:25:27 AM7/8/10
to Autofac
Hi,

I'm trying to find a way to handle the following scenario:

interface IServiceA {
}

class ServiceA : IServiceA {
}


interface IServiceB {
}

class ServiceB : IServiceB {
ServiceB(ServiceA a) {
}
}


class ServiceC {
ServiceC(IServiceA a, IServiceB b) {
}
}

Assuming that all services are registered as InstancePerDependency (I
might need to create independent instances of any one service), How
can I ensure that when I resolve an instance of ServiceC, the ServiceA
instance is the same for both itself, and its IServiceB dependency?

Thanks,
Ilia Jerebtsov

tillig

unread,
Jul 9, 2010, 10:58:10 AM7/9/10
to Autofac
If you register them all as InstancePerDependency, you can't do what
you're trying to do (to the best of my knowledge). You can, however,
do what you want through the judicious use of lifetime scopes.

For example, register the services as InstancePerLifetimeScope:

var builder = new ContainerBuilder();
builder.RegisterType<ServiceA>().As<IServiceA>().InstancePerLifetimeScope();
builder.RegisterType<ServiceB>().As<IServiceB>().InstancePerLifetimeScope();
builder.RegisterType<ServiceC>().As<IServiceC>().InstancePerLifetimeScope();
var container = builder.Build();

Then before you resolve your services, create a new lifetime scope
like this:

IServiceC resolved1 = null;
using (var scope = container.BeginLifetimeScope())
{
resolved1 = scope.Resolve<IServiceC>();
}

This will ensure that, just for this resolution of the IServiceC
instance, all of the IServiceA instances will be the same.

For testing purposes, I added some public properties to the classes so
I could access the instances getting set and this tests out:

IServiceC resolved1 = null;
using (var scope = container.BeginLifetimeScope())
{
resolved1 = scope.Resolve<IServiceC>();
Assert.AreSame(resolved1.A, resolved1.B.A);
}

IServiceC resolved2 = null;
using (var scope = container.BeginLifetimeScope())
{
resolved2 = scope.Resolve<IServiceC>();
Assert.AreSame(resolved1.A, resolved1.B.A);
}
Assert.AreNotSame(resolved1, resolved2);


Hope that helps,
-T

tillig

unread,
Jul 9, 2010, 10:59:42 AM7/9/10
to Autofac
Minor typo in that second assertion, but you get the idea. :)

Nicholas Blumhardt

unread,
Jul 10, 2010, 7:47:53 PM7/10/10
to aut...@googlegroups.com
Looks like the right approach.

Depending on how the services get instantiated/used, you could also take a dependency on Owned<IServiceC> to get the same effect - the .Value member will be resolved in its own lifetime scope in the same way as below, but without the explicit container dependency.

I've realised there's very little documentation on how Owned is supposed to work, so I just collated a bit of information into http://code.google.com/p/autofac/wiki/OwnedInstances - there's at least a location to collect FAQ now :)

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To post to this group, send email to aut...@googlegroups.com.
To unsubscribe from this group, send email to autofac+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/autofac?hl=en.


Ilia Jerebtsov

unread,
Jul 12, 2010, 7:42:10 AM7/12/10
to Autofac
Thank you for the suggestions.

I've considered using a lifetime scope, but then I lose the ability to
create new instances within the scope, which I might have needed. In
the end, I decided that this kind of very specific initialization
requirement in ServiceC is fragile design, and reworked my classes to
remove it.

Autofac seems to be very good at pointing out bad design - if there's
no simple way of doing something, it's likely that I'm doing something
wrong. And that's great. :)

Thanks,
Ilia Jerebtsov

gryzykhi...@gmail.com

unread,
Nov 18, 2015, 6:35:11 PM11/18/15
to Autofac
@Travis Illig
Using scopes is good approach, but keep in mind that it will cause you issues in case if AutoFac resolves any instances of IDisposable. The problem is that when you dispose of scope, it disposes of all IDisposable classes.
Reply all
Reply to author
Forward
0 new messages