ReactiveUI,View / ViewModel注入和DI一般

最近我试图让自己进入UI开发的新时代并发现了ReactiveUI。 我喜欢它的陈述性。

我想做一个完整的切换,所以我试着理解在ReactiveUI的这个新世界中是如何做出的。 我选择了ReactiveUI,因为我看到这是由一个非常聪明的人(Paul C. Betts)维护的。

我对它很陌生,我可能会对StackOverflow充满疑问,因为我拥有巨大的力量,我认为它值得学习和掌握

让我们进入细节:

我一直使用View-First。 我是Cinch Framework的资深用户( http://cinch.codeplex.com/ )

它使用MEF将ViewModel注入每个View。 您只需使用[ViewModel(“SampleView”)]装饰ViewModel并向View添加一个附加属性(ViewModelLocator.ViewModel =“SampleView”),每当View加载时,相应的ViewModel将被实例化并注入其中DataContext与您选择的生命周期。

这种机制虽然有效,但也有一些不便之处。 最糟糕的是:它使用了一个定位器。

正如Mark Seemann在他的书中所说,ServiceLocator是一种应该避免的反模式。

  1. 所以我的第一个问题是:ReactiveUI是建立在基于Locator的基础架构之上吗?
  2. View-First还是ViewModel-First? 在良好实践,解耦,SOLID以及像我这样的疯狂,亲微软清洁代码爱好者关注的问题方面,哪些更好? 哪个会让我睡得更好,并为我的应用程序提供所有那些可靠性的好处?

保罗可能会对官方的回答表示赞同,但作为一个使用该框架进行一些项目的人,我会投入0.02美元,但绝不是专家。

1)我是Mark Seemann的忠实粉丝,我同意他关于ServiceLocator反模式的结论。 虽然ReactiveUI确实使用了定位器“Splat”,但我不认为它建立在基于Locator的基础架构之上。 有一些Global项目被用作线程调度程序和一些主要设置,但这些项目主要在应用程序启动时设置(如任何DI容器),并且您不会直接在类中处理它们。 唯一真正的位置是ViewModelHost控件,它使用ViewModelHost上的特定接口( IViewFor )来注册ViewModel。 这比属性方法更好,因为它使ViewModels幸福地不知道Views。 但这发生在控件本身并且是框架的一部分,所以我不觉得它是滥用ServiceLocator反模式。 我觉得在设置DI容器时注册其他任何东西都没有什么不同。

2)根据我使用ReactiveUI后的经验,我的视图变得非常简单。 基本上打了一些基本的XAML来获得正确的外观和布局,在后面的代码中实现IViewFor ,并在构造函数中完成所有绑定,现在我发现使用ReactiveUI比在XAML中更容易(尽管你仍然可以,如果你想至)。 然后,逻辑方面的一切都在ViewModels中完成。 我认为我通常只做一个ViewModel First方法,因为我需要定义它(或至少它的接口)来为View实现IViewFor<> 。 我喜欢类型检查和东西(我喜欢在构造函数中绑定而不是在XAML中的另一个原因)。 但根据我的经验,我不认为有充分理由以这种或那种方式做到这一点。

ServiceLocator是一种应该避免的反模式。

我一般认为围绕IoC / DI的许多建议在“跨平台移动应用程序”领域都非常糟糕,因为你必须记住他们的很多想法是针对网络应用程序而不是移动应用程序或桌面应用程序编写的。

例如,绝大多数流行的IoC容器只关注热缓存的解析速度 ,而基本上完全忽略了内存使用或启动时间 – 这对于服务器应用来说是100%的好,因为这些并不重要; 但对于移动应用程序? 启动时间很长。

Splat的服务位置解决了RxUI的许多问题:

  1. 服务位置很快 ,几乎没有设置开销。
  2. 它封装了几个不同的常见对象生命周期模型(即’每次创建新的’,’单例’,’懒惰’),只需通过不同的方式编写Func
  3. 这是Mono Linker友好(一般)
  4. Service Location允许我们在特定于平台的代码中注册类型,但在PCL代码中使用它们。

使用Service Locator的最佳方式

事实上,我一般都认同Mark Seemann,因为构造函数注入是首选的方法 – 这是我真正喜欢的模式:

  public SuspensionHost(ISuspensionDriver driver = null) { driver = driver ?? Locator.Current.GetService(); } 

这使用Service Location接口作为默认接口,但前提是调用者没有在构造函数中给出明确的接口。 在unit testing运行器中测试比尝试构建假的IoC容器更直接,但仍然在运行时回退到默认实现。

View-First还是ViewModel-First?

您是否可以在ReactiveUI中使用基于VM的路由(即RoutedViewHost,IScreen,RoutingState和朋友)取决于您所在的平台:

  • WPF,Xamarin表格:绝对
  • WP8,WinRT:你可以让它工作,你会失去一些过渡和细节
  • Android,iOS Native:非常难以开展工作