WPF MVVM 应用程序的测试性开发

在开始构建儿子的婴儿房的周末,找到了一个借口。无论如何,这已经足够了。这篇文章将是一系列三篇文章中的第一篇,将解释目前是如何以一种可测试的方式开发WPFMVVM应用程序的,几乎不需要代码后置处理。

案例研究将是一个小型的持续集成客户端,它将轮询构建服务器并允许部署构建,并显示当前部署状态的部署图。用例可能对大多数人来说并不相关,所以将尽量不太多地关注它们。

可以从下载这篇文章的源代码。

为什么需要控制反转/依赖注入

封装,封装,封装,可测试性,它促进了开放封闭原则。它如何帮助这些原则将变得清晰,正如通过案例研究的介绍。

Castle容器

使用Castle的依赖注入框架来托管所有的依赖项,包括视图模型,所以花几分钟时间看看他们的。

在Visual Studio中创建一个新的WPF应用程序(使用的是VS 2008)。现在为了简单起见,将添加一点代码后置处理到Window1.cs。将在以后的文章中解释如何摆脱这个代码后置处理(重构出代码后置处理),但现在只想开始。

在window1.cs的构造函数中,将在InitializeComponent方法调用之前添加以下代码行:

C# DataContext = Container.GetA();

对于所有MVVM纯粹主义者(理所当然!),将向展示如何在单独的帖子中摆脱这个代码后置处理。

Container是自己的静态网关到Castle微内核。想要抽象这个,以便容器框架将是单元测试友好的,这样就可以轻松地交换容器实现而不改变代码。以下是静态容器网关的简单实现:

C# public static class Container { private static IContainer _containerImplementation; public static void InitializeContainerWith(IContainer containerImplementation) { _containerImplementation = containerImplementation; } public static T GetA() { return _containerImplementation.GetA(); } }

现在需要在容器中注册一个MainViewModel实现。在App.xaml代码后置处理中,将以下代码添加到OnStartupMethod中:

C# protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var container = new CastleKernalContainer(); container.RegisterA(typeof(MainViewModel)); Container.InitialiseContainer(container); ... }

CastleKernalContainer实现是自己的IContainer实现,它基本上是castle内核的包装器:

C# public interface IContainer { T GetA(); void RegisterA(Type type); } public class CastleKernalContainer : IContainer { private readonly IKernel _castleKernel; public MicrokernelContainer() : this(new DefaultKernel()) { } public MicrokernelContainer(IKernel castleKernel) { _castleKernel = castleKernel; } public T GetA() { return (T)_castleKernel.Resolve(typeof(T)); } public void RegisterA(Type implementation) { _castleKernel.AddComponent(typeof(T).FullName, typeof(T), implementation); } }

现在在Window1.xaml中,需要以下内容:

XML <Window x:Class="DependencyInjection.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Apollo" WindowStartupLocation="CenterScreen"> <Grid> <ContentControl Content="{Binding}" /> </Grid> </Window>

在这里,将窗口的内容设置为datacontext。这就是WPFMVVM形成完美关系的地方!可以在App.xaml中为MainViewModel定义一个数据模板,如下所示:

XML <application xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:class="DependencyInjection.App" xmlns:dependencyinjection="clr-namespace:DependencyInjection" startupuri="Window1.xaml"> <application.resources> <datatemplate datatype="{x:Type DependencyInjection:MainViewModel}"> <mainview /> </datatemplate> </application.resources> </application>

现在定义MainView作为一个用户控件:

XML <usercontrol xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:class="DependencyInjection.MainView" width="300" height="300"> <grid> <textblock text="Hello World !" /> </grid> </usercontrol>

就是这样!现在有一个简单的依赖注入MVVM框架,适用于任何WPF应用程序。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485