问题
A beginner question on lifetimescopes with autofac and when to use them, in a xamarin app.
As mentioned in this article (https://nblumhardt.com/2011/01/an-autofac-lifetime-primer/) which is referred to by the autofac documentation (http://docs.autofac.org/en/latest/lifetime/) they hammer a lot on not resolving from the root container but using seperate lifetimescopes and thinking in terms of units of work because autofac hold referenences to disposable objects even if they are not used anymore until the scope they were created on is disposed, and therefore there is the danger of memory leaks.
However when developing a Xamarin application and looking for examples, I find no examples of this usage, also with using an IoC container as a service locator anitpattern in mind, when whould this be used? (https://xamarinforms.wordpress.com/tag/dependency-injection/)
These articles show a 'best practice' example of setting up navigation in a xamarin app and resolving the necessary viewmodels and setting them as bindingcontext to pages: https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/navigation/ and https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/mvvm/#automatically_creating_a_view_model_with_a_view_model_locator Not sure if this is best practice or just the best way to do things in xamarin forms.
However, now what happens when these viewmodels get instantiated by autofac and one of these models have dependencies on classes that are disposable?
When a viewModel is requested a new instance is resolved matched with a page and put on a navigation stack. So when navigating pages the stack grows bigger and bigger, autofac keeps references to all the disposable objects, and during the lifetime of the application (everything gets resolved from the main container, no seperate scopes are used) which could last a long time, is there a risk here of running into memory issues? When do all these unused objects get garbage collected if there is a risk they are still referenced? Probably I am missing some understanding of how this actually works or making a mistake in its usage but note how the InternalNavigateToAsync method from the https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/navigation/ just keeps adding pages to the stack when navigating to another page..
PS. On a side note, this, which looks fine (scope.Resolve):
using(var scope = container.BeginLifetimeScope())
{
for(var i = 0; i < 100; i++)
{
var w = scope.Resolve<Worker>();
w.DoWork();
}
}
and this from (http://docs.autofac.org/en/latest/register/registration.html and some other places as well..):
using(var scope = container.BeginLifetimeScope())
{
var reader = container.Resolve<IConfigReader>();
}
is used in the autofac documentation, I suppose this last one is a typo?? (container.Resolve instead of scope.Reslove with a useless(?) scope block around it resolving from the main container anyway within this scope block...
回答1:
Regrettably, AutoFac and other so-called "IOC" Containers and/or frameworks tend to exaggerate what they can do. They are also not very IOC-like.
If I create this plain-vanilla class:
public class NonDerivedClass
{
using (var scope = contaner.BeginLifetimeScope())
{
var reader = container.Resolve<IConfigReader>();
}
}
... and then I instantiate, use, and finally destroy NonDerivedClass, how would the reader know to be destroyed as well? And I do mean, according to C#, using what mechanism? There isn't one. No event is raised by an object as it goes out of scope and becomes eligible for garbage collection.
There is no evidence that your examples implement IDisposable, but even if they did, IDisposable does not provide a "death event". So that is not the solution.
In this case. your local "reader" variable dies with the NonDerivedCass because it is private to that class. But the globally stored instance of the IConfigReader stays alive for the entire app lifespan.
Global variables are not your friends. Stick to SOLID design principles (which see).
The complete code for these remarks is at https://github.com/marcusts/xamarin-forms-annoyances. See relevant solutions are AwaitAsyncAntipattern.sln and IocAntipattern.sln.
The GitHub site also provides links to a more detailed discussion on this topic.
来源:https://stackoverflow.com/questions/46112639/xamarin-autofac-navigationservice-and-beginlifetimescope