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

Fixes #1108 - Stop secondary invocation of OnActivating() handlers with decorated instance #1110

Merged
merged 6 commits into from
Apr 29, 2020

Conversation

VonOgre
Copy link
Contributor

@VonOgre VonOgre commented Apr 25, 2020

Fixes #1108, specifically the most critical part, as it stops the casting exception from occurring or unexpectedly calling an OnActivating() delegate multiple times.

It also brings OnActivating() back into alignment with the other lifetime events when decorators are in play

- Remove broadcast of OnActivating with decorated instance if decoration occured, as it is inconsistent with OnPreparing and OnActivated behavior
@VonOgre VonOgre changed the title Issue 1108 - Stop secondary invocation of OnActivating() handlers with decorated instance Fixes #1108 - Stop secondary invocation of OnActivating() handlers with decorated instance Apr 25, 2020
@@ -102,9 +102,6 @@ public object Execute()
_activationScope,
resolveParameters);

if (instance != decoratorTarget)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something specific, you wouldn't actually want to raise the Activating event again for the same registration, but specify the decorated instance. CreateInstance() already raises Activating for the original, so this block that's removed is a secondary occurrence only happening with decorators in play.

@alsami alsami self-requested a review April 25, 2020 06:19
alsami
alsami previously approved these changes Apr 25, 2020
Copy link
Member

@alsami alsami left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexmg @tillig just tested it quickly locally this indeed stops the second raise the event.

Copy link
Member

@tillig tillig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be I'm just being overly cautious, but we should probably add some related tests to make sure there aren't any side effects here.

  • I don't see any tests that ensure Activating only happens once, like, in general, without decorators. We should probably add some here. (Or, if you saw them, let me know where; I could be just missing them.) Be sure to include tests for a reflection-based registration (RegisterType<T>), a lambda registration (Register(ctx => x)), and a provided instance (RegisterInstance(obj)). It might also be good to add the lambda and provided instance registration types to the decorator tests to make sure the right number of events are being raised there.
  • Update the existing tests you added to make sure Activating is also checked on the decorators - there should be an Activating for the instance being decorated and also one for each decorator.

Sorry if that's a little painful. It just appears that's a place where (as you've encountered) we probably need some additional testing to ensure we're not regressing or breaking something else by virtue of fixing this issue.

@VonOgre
Copy link
Contributor Author

VonOgre commented Apr 27, 2020

@tillig - I can definitely dig into the first one and shore up some additional tests, for the sake of adding robustness, but the second ask gives me pause, since that seems to contradict the fix that I added. Alternatively, are you asking that appropriate tests be added to ensure Activating events are raised for decorating classes that have their own OnActivating() handlers added?

I don't know that decorating classes can have their own OnActivating() handlers, because all of the RegisterDecorator() overloads are void, so there's nothing to add a handler to. At best, you might be able to have something akin to:

builder.Register<MyDecorator>().OnActivating(...);
builder.RegisterDecorator<MyDecorator, IService>();

where you might have an Activating event that works, at that point?

I'll do some more investigation, but wanted to make sure I understood the ask!

@tillig
Copy link
Member

tillig commented Apr 27, 2020

Oh, no, you're right; I was thinking about the way the decorators automatically share the lifetime of the component to which they're attached and incorrectly extrapolated that there are also the same lifetime events for each decorator. Could have sworn that was a thing. Hmmm.

Anyway, skip that second bullet. If we have some tests that just ensure we haven't incorrectly removed events or doubled events where they already were supposed to be, we'll be good. Sorry for the confusion. It's a hell of a day today. :)

@VonOgre
Copy link
Contributor Author

VonOgre commented Apr 27, 2020 via email

Copy link
Member

@tillig tillig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super awesome! Thanks!!!

@tillig tillig merged commit 8790ac6 into autofac:develop Apr 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

OnActivating()/OnActivated() not playing nicely with RegisterDecorator()
3 participants