在开始构建儿子的婴儿房的周末,找到了一个借口。无论如何,这已经足够了。这篇文章将是一系列三篇文章中的第一篇,将解释目前是如何以一种可测试的方式开发WPFMVVM应用程序的,几乎不需要代码后置处理。
案例研究将是一个小型的持续集成客户端,它将轮询构建服务器并允许部署构建,并显示当前部署状态的部署图。用例可能对大多数人来说并不相关,所以将尽量不太多地关注它们。
可以从下载这篇文章的源代码。
封装,封装,封装,可测试性,它促进了开放封闭原则。它如何帮助这些原则将变得清晰,正如通过案例研究的介绍。
使用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。这就是WPF和MVVM形成完美关系的地方!可以在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>