最佳实践(3):Windows应用开发

这是Futurice公司的Windows 8.x 和 Windows Phone 8.x 应用开发者的经验教训。通过参考这些指南能够避免重复造轮子。如果你对iOS或者Android开发感兴趣,一定也要去看一下他们的《iOS开发最佳实践》和《安卓开发最佳实践》。

欢迎反馈,但是在这之前请先阅读这个指南


C# 开发一般都用 Visual Studio

使用Visual Studio Pro或更好的版本

Visual Studio实际上是用来开发Windows应用的IDE。免费的精简版本对于入门来说不错,但是缺少一些重要的特性,比如支持额外的扩展。专业版本能通过一次安装提供所有不同项目类型的支持、额外开发特性、支持扩展、和一些支持团队合作的特性。特惠版主要添加了一些优于普通单元测试的内建测试支持,而旗舰版添加了增强的调试、架构和代码分析工具。

使用Productivity Power工具(2013)

来自微软的一个免费 VS 开发扩展。它缺少一些同类产品——比如JustCode或者ReSharper——拥有的特性。不过这似乎不会使IDE的效率变低。

使用NuGet

Nuget是微软的一个包管理工具。在新的Visual Studio中预装了一个叫NuGet Package Manager的扩展。注意:当不需要在解决方案中包含源代码时,请把它作为外部引用。

使用Package Restore

根据NuGet的文档:

自从NuGet2.7开始,当Build开始时,NuGet 的Visual Studio扩展集成进了Visual Studio 的Build事件和修复失去的包的过程中。

这种包修复方法有若干优点:

  • 不需要专门为你的工程或解决方案去激活它。Visual Studio 在你的工程在被构建之前就会自动下载缺失的包,并且团队成员不需要了解NuGet Package Restore的详细情况。
  • 在你的项目或解决方案中不需要额外的目录或文件。
  • Visual Studio 调用 MSBuild 之前前,会恢复(缺失的)包。这可以让通过目标/属性文件导入的扩展 MSBuild 的包在 MSBuild 启动之前恢复,以确保成功构建(build)。
  • 与用Visual Studio创建的ASP.NET 网站项目兼容。

如果你点击了Visual Studio中的”Enable NuGet Package Restore”按钮后你会使用旧的包修复工具。如果是这样,你应该迁移至:NuGet docwith pictures.

将代码分成小段的方法,以提升堆栈跟踪和堆栈调用视图的性能

为了可重用性,代码通常被分割成小段的方法块。然而即使不打算重用它们,也应该将方法拆分。方法名记载了代码包含的内容。当调试时这给予你更多关于调用堆栈信息,和更好的异常的堆栈跟踪信息。堆栈跟踪更多应用到发布版的程序中,在那里面代码行的信息已经丢失了。

在跟踪的时候使用caller information属性

当为任意的参数添加CallerMemberName、CallerFilePath 或者 CallerLineNumber属性的时候,这个参数的相关信息将被设置成调用者的文件路径、行号和成员名。这些值将在编译时被设置进方法调用中,不会影响执行效率,也不会被混淆的代码所影响。

来自MSDN的例子:

你的HTTP应用使用HTTPClient

在各种各样的可用的HTTP API中,HttpClient是一个新的支持 异步/等待 和自动请求解压的API。通过 异步/等待的方式来使用它来保持代码的简洁易读。

了解计时器

这里有为了不同目的的不同的计时器。比如WinRT的DispatcherTimer(定时器),WP Silverlight 的DispatcherTimer ThreadPoolTimer。另外还有Observable.Timer,Task.Delay。最后但不是最重要的Thread.Sleep

返回一个IEnumerable的时候,用yield

而不是写一些像下面这样的东西:

而是要这样写:

如果没有yield返回被调用,它会自动返回一些空的IEnumreable。当你想获取一个IEnumreable的时候这样做会避免一些空引用异常。当且仅当可能的迭代器需要的时候,这个yield方法才会运行。比如,下面的语句仅仅创建了一个Galaxy实例,避免了一些不必要的运行过程。

LINQ查询显式转换成集合,以避免不必要的重复运算

可能首先需要了解的关于LINQ的事是,每次访问查询结果的时候,它创建的查询都会被执行。有时候你的确想要这样。然而,你经常仅仅想要运行这个查询一次,多次访问被查询的结果。为了避免不必要的重复计算以及查询结果变化带来的错误,请使用ToArray、ToList等扩展方法来执行查询并将结果保存到集合中。

所以不要这样做:

而要这样做:

不要被IObservable超时蛊惑(这个IObservable资源,IObservable firstTimeout, Func> timeoutDurationSelector

现在,这是一个接口,所以不同的实现呈现的结果也不一样。以下的应用都至少是相对于在System.Reactive.Linq.Observable中的实现而言的.

很容易想到应该这样做:

然而,这样很容易就超时了.所以正确的使用方法是:

所以,当传递的IObservable完成时会发生超时,而不是在传递的TimeSpan的持续时间过了以后超时.

Windows App 开发

不要给你的自定义控件的名字硬编码

当编写自定义或用户控件的时候,不要给控件的名字属性设置一个固定的值.在XAML中这意味着为根节点设定x:Name属性。

每一个在PresentationFrameworkCollection中的从属对象必须有一个独特的名字,并且如果最终在同一个PresentationFrameworkCollection中添加了两个有同样名字的控件,你会遇到这样的情况:

当你不硬编码的时候,框架(framework)会为每一个实例生成一个专属的名字。

当将属于一个依赖对象的多个依赖属性绑定到一起时要格外小心

将会有两个可能的意外情况:

顺序问题

案例:12

捆绑到DataContext改变了默认的捆绑资源

比如,以下的XAML在MyAdViewModel中而不是在MyPageViewModel寻找AdVisiblity。改变捆绑的顺序没有任何影响。(但是会首先在MyPageViewModel中寻找,然后在MyAdViewModel中寻找)。

会发生这种事情是因为”{Binding PropertyName}”是以下的简写:

“{Binding Path=DataContext.PropertyName, Source={RelativeSource Self}”

事实上它将 DataContext中的自己的属性,和在这个对象中的PropertyName属性绑定在了一起。当DataContext没有设置时,它会自动从父类继承。

使用CallerMemberName属性或者一个LINQ表达式来帮助通知属性的改变

很多的MVVM框架已经在视图模型中提醒属性的改变。不过不要用其中的任何一种,你应该为自己创建一个基础视图模型类。但是应当注意创建一个LINQ表达式所造成的性能开销。

比如:

如果你在ViewModels中使用Rx,也请使用ReactiveProperties ReactiveCommands

如果你还没有用过能方便地从XAML中绑定互动代码的库的话,去搜索一下ReactiveProperty 和 ReactiveCommand 帮助类。或者直接在面选用一个由Tomasz Polanski创建的 reactive工具库。

收藏 2 评论

关于作者:Nikkko

在校大学生,精通C语言、Python的拼写和读法,熟悉各种逆向调试工具的安装,相信不喜欢搞前端的硬件攻城狮不是好码农。@Nikkko 个人主页 · 我的文章 · 10

相关文章

可能感兴趣的话题



直接登录
最新评论
跳到底部
返回顶部