Xamarin,Autofac,NavigationService和BeginLifetimeScope

Ste*_*ven 5 dependency-injection autofac object-lifetime xamarin

在xamarin应用程序中,有关使用autofac的lifescopescope以及何时使用它们的初学者问题。

如本文所述(https://nblumhardt.com/2011/01/an-autofac-lifetime-primer/),autofac文档(http://docs.autofac.org/en/latest/ (lifetime /),他们在不从根容器中解决问题,而是使用单独的lifescope并根据工作单位进行思考的过程中付出了很多努力,因为autofac保留了对一次性对象的引用,即使它们不再使用,直到它们被创建的范围都被废弃为止,因此存在内存泄漏的危险。

但是,在开发Xamarin应用程序并查找示例时,我找不到这种用法的示例,也没有想到将IoC容器用作服务定位器anitpattern,何时使用?(https://xamarinforms.wordpress.com/tag/dependency-injection/

这些文章展示了一个“最佳实践”示例,该示例在xamarin应用程序中设置导航并解析必要的视图模型,并将其设置为与页面的绑定上下文:https : //developer.xamarin.com/guides/xamarin-forms/enterprise-application- pattern / navigation /https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/mvvm/#automatically_creating_a_view_model_with_a_view_model_locator 不知道这是xamarin形式的最佳实践还是最佳方法。

但是,当这些视图模型由autofac实例化并且这些模型之一依赖于可抛弃的类时,会发生什么呢?

当请求viewModel时,将解析一个与页面匹配的新实例,并将其放在导航堆栈中。因此,在浏览页面时,堆栈变得越来越大,autofac会保留对所有一次性对象的引用,并且在应用程序的生命周期中(所有内容都可以从主容器中解析出来,没有使用单独的作用域)可能会持续很长时间。这里有遇到内存问题的风险吗?如果仍然存在引用这些未使用对象的风险,何时将所有这些未使用对象收集为垃圾?可能我对这实际上是如何工作缺少某种理解,或者在用法上犯了一个错误,但请注意https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/navigation/中的InternalNavigateToAsync方法 只是导航到另一个页面时将页面添加到堆栈中。

PS。在侧面说明,这看起来不错(scope.Resolve):

using(var scope = container.BeginLifetimeScope())
{
  for(var i = 0; i < 100; i++)
  {
    var w = scope.Resolve<Worker>();
    w.DoWork();
  }
}
Run Code Online (Sandbox Code Playgroud)

并且来自(http://docs.autofac.org/en/latest/register/registration.html和其他一些地方。):

using(var scope = container.BeginLifetimeScope())
{
  var reader = container.Resolve<IConfigReader>();
}
Run Code Online (Sandbox Code Playgroud)

是在autofac文档中使用的,我想这最后一个是错字了吗?(container.Resolve而不是scope.Reslove,它周围有一个useless(?)范围块,无论如何在这个范围块内从主容器中解析...

Ste*_*cus 0

遗憾的是,AutoFac 和其他所谓的“IOC”容器和/或框架往往夸大了它们的功能。它们也不太像国际奥委会。

如果我创建这个普通类:

public class NonDerivedClass
{
    using (var scope = contaner.BeginLifetimeScope())
    {
        var reader = container.Resolve<IConfigReader>();
    }
}  
Run Code Online (Sandbox Code Playgroud)

...然后我实例化、使用并最终销毁 NonDerivedClass,读者怎么知道也被销毁了?我的意思是,根据 C#,使用什么机制?没有一个。 当对象超出范围并有资格进行垃圾回收时, 不会引发任何事件。

没有证据表明您的示例实现了 IDisposable,但即使实现了,IDisposable 也不会提供“死亡事件”。所以这不是解决方案。

在这种情况下。你的本地“reader”变量会随着 NonDerivedCass 一起消失,因为它是该类的私有变量。但全局存储的 IConfigReader 实例在整个应用程序生命周期内保持活动状态。

全局变量不是你的朋友。坚持 SOLID 设计原则(参见)

这些评论的完整代码位于https://github.com/marcusts/xamarin-forms-annoyances。查看相关解决方案是AwaitAsyncAntipattern.sln和IocAntipattern.sln。

GitHub 站点还提供了有关此主题的更详细讨论的链接。