Xamarin,Autofac,NavigationService和BeginLifetimeScope

时间:2017-09-08 09:03:09

标签: xamarin dependency-injection autofac object-lifetime

关于使用autofac的生命时间镜以及何时使用它们的初学者问题,在xamarin应用程序中。

正如autofac文档(https://nblumhardt.com/2011/01/an-autofac-lifetime-primer/)所引用的这篇文章(http://docs.autofac.org/en/latest/lifetime/)所提到的那样,他们在不从根容器中解析但是使用单独的生命周期镜并考虑到工作单元,因为autofac保持对一次性物体的引用,即使它们不再被使用,直到它们被创建的范围被处理掉,因此存在内存泄漏的危险。

然而,在开发Xamarin应用程序并查找示例时,我发现没有这种用法的例子,当使用IoC容器作为服务定位器anitpattern时,我会在何时使用它? (https://xamarinforms.wordpress.com/tag/dependency-injection/

这些文章展示了一个最佳实践'在xamarin应用程序中设置导航并解析必要的视图模型并将其设置为pagescontext到页面的示例: https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/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();
  }
}

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

using(var scope = container.BeginLifetimeScope())
{
  var reader = container.Resolve<IConfigReader>();
}

用于autofac文档,我想这最后一个是错字? (container.Resolve而不是scope.Reslove,在这个范围块内,无论如何都要从主容器中解析出无用的(?)范围块......

1 个答案:

答案 0 :(得分:0)

令人遗憾的是,AutoFac和其他所谓的“IOC”容器和/或框架往往会夸大他们能做的事情。它们也不像IOC那样。

如果我创建这个普通的类:

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

...然后我实例化,使用并最终销毁NonDerivedClass,读者如何知道也会被销毁?我认为,根据C#,使用什么机制?没有一个。 对象没有引发事件 ,因为它超出范围并有资格进行垃圾回收。

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

在这种情况下。您的本地“reader”变量会与NonDerivedCass一起消失,因为它对该类是私有的。但是全局存储的IConfigReader实例在整个应用程序生命周期

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

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

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