Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoActivate / IStartable doesn't work for components configured within a LifetimeScope #567

Closed
llaszko opened this issue Aug 28, 2014 · 13 comments

Comments

@llaszko
Copy link

llaszko commented Aug 28, 2014

I've encountered a problem with auto activation of components specifically configured only during creation of a LifetimeScope. Like in the example below:

https://gist.github.com/llaszko/4143edda2eb7a8118e54

it looks like ContainerBuilder.StartStartableComponents isn't called by an overload of ContainerBuilder.Update called during the LifetimeScope creation.

I think it would be nice to at least have public access to ContainerBuilder.StartStartableComponents or ideally allow components specifically configured in a dependent scope to support AutoActivate properly.

@ilya-g
Copy link

ilya-g commented Aug 29, 2014

Stumbled on this a day ago too!
However this misleading behavior is inherent to autoactivated components for a long time.

@daniellittledev
Copy link

I ran into this as well, does IStartable also not work?

@Rophuine
Copy link

I ran into something similar while using the AutofacNancyBootstrapper. The hooks to configure the container look like:
protected override void ConfigureApplicationContainer(ILifetimeScope existingContainer)
{
...
}

The most discoverable way to update the registrations is:
containerBuilder.Update(existingContainer.ComponentRegistry);
This, as noted, doesn't call StartStartableComponents.

However, you can work around the problem by casting the ILifetimeScope to an IContainer:
containerBuilder.Update((IContainer)existingContainer);

This gets an overload which does call StartStartableComponents.

It's relying on an implementation detail, but unfortunately I'm not sure if the problem is with Autofac, or with Nancy's hook - which should provide an IContainer instead of an ILifetimeScope. I suspect the latter, but if Nancy fixed that, it would be a very breaking change.

Perhaps Autofac should complain about an AutoActivate registration made against a component registry (instead of a container)? At least it would be an explicit error, instead of just having AutoActivate registrations mysteriously not work.

@daniellittledev
Copy link

A bit of an update, it seems like this is sort of by design as the documentation does say.

In both cases, at the time the container is built, the component will be activated.

Although I don't see anything that would technically stop registrations that use AutoActivate from being activated by BeginLifetimeScope.

Currently after I create a new ILifetimeScope I'm using the ComponentRegistry to find all the AutoActivate services and then activating them.

@Rophuine therefore an explicit error would break this

@Rophuine
Copy link

Yeah, I had a suspicion that any solution proposed would risk breaking existing hacks around the behaviour.

Given that AutoActivate is a thing which happens on container build instead of scope creation, I'd suggest coming up with an alternative marker that something should be started on creation of a scope - implement a new interface (something like IActivatesOnBeginLifetimeScope) and then just resolve an IEnumerable of those.

Breaking changes are rare, but you would be protecting yourself against any future breaking changes designed to prevent people running into this issue.

@daniellittledev
Copy link

@Rophuine I could see this going the other way as well though

AutoActivate would be a useful feature in the context of BeginLifetimeScope and I think it fits what the API suggests more accurately.

@tillig tillig changed the title AutoActivate doesn't work for components configured within a LifetimeScope AutoActivate / IStartable doesn't work for components configured within a LifetimeScope Mar 31, 2016
@AqlaSolutions
Copy link

From #731:

Assume I have these registrations:

        di.RegisterType<PushNotificationsManager>()
            .As<IPushNotificationsManager>()
            .InstancePerMatchingLifetimeScope("App")
            .AutoActivate();
        di.RegisterType<ChatMasterService>()
            .As<IChatMasterService>()
            .InstancePerMatchingLifetimeScope("App")
            .AutoActivate();
        di.RegisterType<User>()
            .As<IUser>()
            .InstancePerMatchingLifetimeScope("User")
            .AutoActivate();

AutoActivate should "understand" that it can't activate them when building a container because they require scopes.

Instead they should be activated when beginning scopes:

// activates PushNotificationsManager and ChatMasterService inside App scope
appScope = container.BeginLifetimeScope("App");

// activates User inside User scope
userScope = appScope.BeginLifetimeScope("User");

So I expect BeginLifetimeScope to use an internal Dictionary<Scope, List<Type>> to find all registrations which should be auto-activated just after creating a scope.

@saltukkos
Copy link

Why did this issue was closed? It's bug, because current implementation of Autoactivate will fail on registration with InstancePerMatchingLifetimeScope in any case, it should not be designed behaviour

@tillig
Copy link
Member

tillig commented Jan 31, 2019

If you look at the issue history, it was closed via a commit that fixes the issue. It will be released in an upcoming version.

@AqlaSolutions
Copy link

@tillig , the commit was added almost a year ago and still not released? Whattt?

@tillig
Copy link
Member

tillig commented Jan 31, 2019

It's in the 4.9.0 beta that's out there right now. [So, I guess, correction to my earlier statement - it's released, just in beta.]

We've asked for feedback on that beta because it adds a bunch of new stuff like a new way to handle decorators and some memory/locking improvements. It's a long beta to make sure all the improvements and changes work well together. Feel free to try the beta and let us know what you think. We don't get much feedback on these things until we break someone in some horrible way and then it's kinda too late, right?

Otherwise, thanks for your patience as the two unpaid project maintainers do the best we can to get things out here. If you're ever interested in helping us speed things up we also put a call for extension project owners out there almost a year ago with zero takers so far. If we can get people to own more of the extensions, we can spend more time focusing on larger core things.

@saltukkos
Copy link

In 4.9.2 the issue is still presented.
If I resigter type as InstancePerMatchingLifetimeScope("someTag").AutoActivate();
my type is still automaticly resolved in root lifetime (and resolving fails, because in my case dependencies are registered in same scope with tag "someTag")

@tillig
Copy link
Member

tillig commented Mar 27, 2019

Tests for the issue here still pass. If you've found something new/additional, please file a new issue with a failing unit test repro so we can better address it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants