ReactiveUI,View / ViewModel注入和DI一般

时间:2014-11-12 23:06:28

标签: c# mvvm reactiveui

最近我试图让自己进入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是建立在一个 基于定位器的基础设施?
  2. View-First或ViewModel-First?在良好实践,解耦,SOLID以及像我这样的疯狂,亲微软清洁代码爱好者关心的问题方面,哪些更好?哪个会让我睡得更好,并为我的应用程序提供所有这些优点?

2 个答案:

答案 0 :(得分:23)

  

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

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

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

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

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

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

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

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

    View-First或ViewModel-First?

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

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

答案 1 :(得分:5)

保罗可能会在官方回答时提出异议,但我会把我的0.02美元作为一个使用该框架进行一些项目的人,但绝不是专家。

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

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