0

How can I get the innermost autofac scope or a named scope in a WPF application? I need this because I use MarkupExtension to resolve VM. So in my MarkupExtension I need the current (inner-most) Lifetimescope.

Thanks

Luka
  • 4,075
  • 3
  • 35
  • 61

2 Answers2

0

I found a way... Container has an event ChildLifetimeScopeBeginning(object sender, ILifetimeScopeBeginningEventArgs args) that I can use for my MakupExtensions like this:

    Container.ChildLifetimeScopeBeginning += (sender, args) =>
            { 
                Debug.Write($"Begin new LifetimeScope: {args.LifetimeScope.Tag??"Unnamed"}");
                //Set the current Lifetime scope for the MarkupExtension
                ContainerTypeResolverExtension.Container = args.LifetimeScope;
            };

So now when every new scope is created I can replace the MarkupExtension inner container. If there is a better way I'm all for suggestions.

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
Luka
  • 4,075
  • 3
  • 35
  • 61
0

There is no native "request lifetime" sort of integration for WPF apps. If you are creating nested lifetime scopes, it's up to you to track them. The need to track your own lifetime scopes - both for creation and disposal - is up to you. Maybe you have some sort of local variable you set, maybe you have some other mechanism.

However, simply adding an event handler on the container won't do it.

Every lifetime scope has its own event for child lifetime scopes beginning.

Let's say you have this:

var builder = new ContainerBuilder();
var container = builder.Build();
var scope1 = container.BeginLifetimeScope();
var scope2 = scope1.BeginLifetimeScope();
var scope3 = scope1.BeginLifetimeScope();

Attaching an event to the container will not find the scopes that are nested outside the container. It will see scope1 but it won't see scope2 or scope3.

You also didn't explain what you're doing with the "most nested lifetime scope" so it isn't clear which of these is "most nested" - seems like scope2 an scope3 are equally nested, so which is the right one?

Finally, there are threading issues to consider. If you're spawning lifetime scopes in async methods or doing anything where different threads will create different scopes, simply tracking [basically] the last created scope will bring you into a world of trouble where you'll end up trying to resolve things from a scope that lives on a thread that doesn't exist anymore.

In the really, really limited case where you do no multithreading/async and never have nested lifetime scopes, maybe handling the event is OK. I would not recommend future readers of the question follow this track.

A better way is somewhat impossible to provide because there's no context given. Do you have a reference to the scope? Can you pass it into the method rather than trying to magically locate it? There are lots of ways to solve the problem, but there's not enough here to provide a good answer. Consider doing some more searches on this, and if it still doesn't yield anything, ask a new question with a lot more information, maybe a repro, and more explanation of what you tried.

Travis Illig
  • 23,195
  • 2
  • 62
  • 85
  • I know all the scopes in application because I create them. And all the scopes are Named scopes. The need for this is that MarkupExtension is a class wpf handles by himself so I can not inject LifetimeScope into it. Also I inject only the specific lifetime scope into it, not any scope. – Luka Oct 11 '19 at 14:01
  • Then the question maybe isn't clear - if you're already creating the scopes yourself you ostensibly already have a tracking mechanism where you keep references... and if you already have that, then the question doesn't make sense because you can use your own tracking mechanism to get the appropriate scope. – Travis Illig Oct 11 '19 at 17:05