什么是最有价值的.net精简框架提示,技巧和疑难解答?
我们广泛的在.Net Compact Framework和Windows Mobile中工作。 我已经看到很多关于ASP.Net应用程序或其他基于.Net的桌面应用程序开发细节的问题,但是没有具体的CF。
其他任何一个移动开发者都可以分享一些事情来开始做,停止做,并避免在Compact Framework中开发时做的事情?
当然:
- 尽可能使用物理设备(而不是仿真器)
- testing多个设备(不同的供应商,不同的型号)
- 集中testing睡眠/唤醒行为
- 当使用MSTESTunit testing时,不要使用私人访问器
- 避免像鼠疫一样的ActiveSync – 使用CoreCon直接debugging
- 熟悉RPM并尽早开始使用
- 尽可能重用对象
- 避免在表单的ctor中进行大量的工作 – 为延迟加载或在后台线程中加载它
- 在可能的情况下按需加载表单(不是一次全部)
- caching经常使用的表单,按需创build不常用的表单
- 保持图像分辨率低
- 如果一个类暴露Dispose 使用它 。 总是。
- 没有应用程序太小,从MVC / MVP模式中受益
- 不要为CF使用Microsoft CAB / SCSF端口(移植它的人明显从未使用过资源受限的设备)
- 如果您要进行任何远程数据/服务活动,请熟悉“偶尔连接”的概念
- 对接和锚定是你的朋友和你的敌人 – testing运行时的屏幕旋转和多个分辨率(即使你认为你不会瞄准他们,因为你可能错误的思想)
- 看看,但不要大量投资设备部署包项目types。 它有很大的限制,可能会咬你。 batch file的工作方式非常好,或者调用CabWiz的自定义MSBUILD任务
- 刷新你的C ++和P / Invoke技能。 你将需要他们。 编写一个有用的CF应用程序几乎是不可能的。
- 编码到目标的最低公分母。
- 部分类是你的朋友,特别是在目标types(PPC,电话,非移动CE)之间划分逻辑。
- 避免从持久性存储中运行应用程序,特别是对于CE和WInMo 5之前的应用程序。复制到RAM并从那里运行,以防止按需分页来杀死您,特别是在hibernate/唤醒循环之后。
- 应用程序不应该关心睡眠/唤醒转换,但这是纯粹的理论。 睡觉唤醒**将*改变你的应用行为,所以再次testing,testing,testing。
- 我有没有提到testing? 特别是在每个设备上,你可以得到你的手? 为您的testing实验室购买易趣的易趣硬件。 拥有更多设备比拥有最新设备更重要,除非您打算使用更新设备的特定function。
- 如果你计划使用蓝牙,请求神圣的介入。 熟悉Widcomm和Microsoft堆栈,并了解它们是不一样的。
- 在精简框架中观看有关内存pipe理的MSDNnetworking广播。 再次观看你第一次错过的东西。
- 注意睡眠/唤醒使内部手柄无效并导致访问违规。 这是更深奥的,但肯定会发生。 例如,如果您正在从存储卡上运行应用程序,则整个应用程序不会加载到RAM中。 正在使用的部分需要分页执行。 这一切都很好。 现在,如果closures设备,驱动程序都会closures。 当您恢复供电时,许多设备只需重新安装存储设备。 当你的应用程序需要更多程序中的需求页面时,它不再是它的位置,而是死亡。 装载商店上的数据库可能会发生类似的行为。 如果您有一个打开的数据库句柄,则在hibernate/唤醒循环之后,连接句柄可能不再有效。
- 安装Platform Builder的评估版本 。 许多事情的源代码就在那里(比如networking用户界面,许多驱动程序等等),当你的P / Invoke代码没有做你期望的事时,你至less有一个地方可以去寻找“为什么”。
5/25/10添加
- 不要期望WinMo下的电源pipe理API在设备上一致或正确地工作 (甚至根本不能)。 事实上,即使使用相同的硬件,它也可能从操作系统构build到操作系统构build。
7/27/10添加
- 如果您在审美UI之后,准备做大量的自定义或手动绘图。
- 如果您正在进行自定义或手动绘图,并且您需要使用透明度,请准备好加载一些挫败感,并且必须直接编写古怪的代码或直接调用本地代码来解决 CF中的缺陷 。
11/22/11添加
- 不要以为BCL中存在一个名称空间或类,它实际上是以任何有用的方式实现的。 证书当然不是 。
我只是添加到列表中,因为他们发生在我身上…
OpenNETCF是一个很好的资源。
他们的智能设备框架是使用.NET Compact Framework进行开发时必须具备的,因为许多Full框架function缺失[我认为有人曾经说.NET Compact Framework是一个围绕NotImplementedException的包装!
这不仅限于 Compact Framework设备,但是由于移动平台上的资源限制,它在开发时会带来更多的难题。
最近我遇到了一个很棒的post,作为pipe理内存泄漏的一个线程的一部分,这帮助我在一个移动应用程序中设置DataGrid.DataSource时发现了一个我不知道的漏洞 。
当绑定一个DataGrid时,你不应该直接使用像这样的东西:
dgDataGrid.DataSource = dsDataSet;
这样每创build一个新的CurrencyManager就不能正确处理。 相反,您要先将DataGrid绑定到BindingSource以避免资源泄漏。
bsData.DataSource = dsDataSet; dgDataGrid.DataSource = bsData;
谁知道? 斯科特·朗廷(Scott Langham)在另一篇文章中写道 感谢Scott!
如果您必须支持多种屏幕尺寸/分辨率,则表单inheritance是一种很好的方法。 基本上你devise你的表格,以适应标准的320×240屏幕。 要支持不同的屏幕大小,只需添加一个新窗体,从自定义窗体(而不是表单)inheritance,然后根据需要重新排列控件。
另一个有用的技巧是以一种方式包装ShowDialog调用,使您可以将父窗体的标题临时设置为“”,这将使应用程序中的所有打开窗体不会显示在正在运行的程序列表中。 另一种增强包装的方法是使用父窗口的句柄PInvoke SetForegroundWindow。 这样可以确保在孩子closures后父母总是会重新出现。 如果没有这个调用,就可能将其他窗口插入父窗体之上的z栈中。
注意SD卡上的encryption。 SqlCE将完全停止工作。 Oracle Lite在encryption下的行为更为险恶,因为它的一部分工作,部分工作不能。
避免SqlCE RDA和合并复制。 如果它们可靠地工作,这些将是非常棒的工具,但是在复制期间networking连接可能意外地被丢弃的情况下(在WM世界中很常见)。 这一点与我的生产应用程序硬我。 我们处理的MS支持技术终于被迫承认,它不能100%工作。 实际的报价:“只是不断尝试复制 – 他们会最终正确合并”。
就像一个供参考,如果你对在Visual Studio 2010中没有Compact Framework支持感到沮丧,那就去这里投票支持它。(并且传播这个词)
MS已经或多或less地放弃了Connect中的现有function请求。 请转到新的用户语音网站投票select此function。
大多数普通的东西需要通过P / Invoke直接调用Windows API。 我发现http://www.pinvoke.net/是在Win32和Windows CE上的P / Invoke的一个很好的资源。
- 如果您打算使用Sql Server 3.5 Compact阅读这个博客 。
- 在SQL Server Compact中存在严重的性能问题,与桌面相比,某些代码在设备上可能会慢100倍,因此请始终在设备上testing数据库代码。
- 设备上的设置单元和性能/集成testing。 也很less有人这样做,这并不复杂,远远超过成本。
- 如果您始终部署代码,则使用networking而不是ActiveSync。 最简单的方法是在设备上设置一个简单的FTP服务器或TCP代理。
使用Compact Framework和SqlCe,性能,内存泄漏和线程同步可能会有很多问题。
遵守的规则,以尽量减less精简框架-SqlCe头痛。
- 使用一个SqlCe连接 – 您可以在连接上使用locking机制来启用多个线程上的一个连接。
- 批量数据插入由于Sqlce引擎而变慢。 使用直接表格插入,直接写入文本文件具有类似的性能优势。
- 在应用程序附近configurationSqlCe连接。 这确保所有资源都被清理。
- 在每次调用数据库之后都要处理所有的命令,datareaders等等。 使用语句是你的朋友。 确保阅读器对象在使用语句等内部命令…
OpenNet CF值得研究 – 甚至免费版本也有一些有用的库,比如FTP,数据网格附加function等。 这是非常有用的,因为CF缺乏很多.net框架function。
unit testing(TDD)可以在.net cf. 但是有问题。
您将使用MSTest。 不是NUnit,MBUnit,XUnit.net等MSTest。
您将需要Visual Studio专业版(尽我所知)。 最简单的入门方法是右键单击想要testing的方法,然后select“创buildunit testing”。 这为您设置了testing项目。 只创build一个testing项目。 它不喜欢有多个。 只要做到这一点来创build项目,并获得所有的依赖设置为您。 然后创build你自己的testing类。
模拟对象可能是一个问题。 RhinoMocks,Moq和TypeMock都依赖于.net cf中没有的东西。 Pex有个项目叫做Stubs,我还在研究。 Pex是一个微软研究项目。 您将最终创build自定义假对象。
testing在设备模拟器上运行。 这意味着他们必须被部署。 如果在首次启动testing运行器时出现奇怪的错误,则可能是在设备模拟器上没有.net 3.5。 首先部署你的项目,然后再次运行testing。
在非testing方面:你得到LINQ to Objects和LINQ to XML。 两者都是天赐之物。 你可以通过WCF与服务器交谈,但是你没有得到所有的端点。
在使用DataGrid时,可以使用Chris Craft博客上最初发布的以下代码,通过列标题对其内容进行sorting:
using System.Windows.Forms; using System.Data; public static void SortDataGrid(object sender, System.Windows.Forms.MouseEventArgs e) { DataGrid.HitTestInfo hitTest; DataTable dataTable; DataView dataView; string columnName; DataGrid dataGrid; // Use only left mouse button clicks. if (e.Button == MouseButtons.Left) { // Set dataGrid equal to the object that called this event handler. dataGrid = (DataGrid)sender; // Perform a hit test to determine where the mousedown event occured. hitTest = dataGrid.HitTest(eX, eY); // If the MouseDown event occured on a column header, // then perform the sorting operation. if (hitTest.Type == DataGrid.HitTestType.ColumnHeader) { // Get the DataTable associated with this datagrid. dataTable = (DataTable)dataGrid.DataSource; // Get the DataView associated with the DataTable. dataView = dataTable.DefaultView; // Get the name of the column that was clicked. if(dataGrid.TableStyles.Count != 0) columnName = dataGrid.TableStyles[0].GridColumnStyles[hitTest.Column].MappingName; else columnName = dataTable.Columns[hitTest.Column].ColumnName; // If the sort property of the DataView is already the current // column name, sort that column in descending order. // Otherwise, sort on the column name. if (dataView.Sort == columnName) dataView.Sort = columnName + " DESC"; else dataView.Sort = columnName; } } } private void dgDataGrid_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { if(dgDataGrid.VisibleRowCount == 0) return; SortDataGrid(sender, e); dgDataGrid.Select(dgDataGrid.CurrentRowIndex); }
-
你会遇到很多错误和限制在.net cf. 你将不得不猴子补丁。 它的丑陋,但你将没有select。
-
你最终会写很多自定义控件。 由于框架中的大部分控件不支持客户通常请求的function。 因此,从一开始就为您使用的每个控件创build自定义控件是一种很好的做法。 即使你开始时可能没有任何东西。 您稍后可以添加自定义逻辑。 无需修改大量现有的代码。
-
如果你需要validation,你可以使用.netvalidation框架
- 在应用程序中的任何位置分配代码是一个好主意。 你可以使用MVC模式。 如果您select使用它,您可以通过使用MobileMVC获得先机
- 如果你需要一个丰富的UI工具包,你可以看看Resco(谷歌它)。
- VSdevise师将是你的主要敌人。
这是我现在所能想到的。
总是用OutlookSession做任何事情
- 在主(应用程序)线程上实例化它
- 在主线程上执行它(我使用一个Control对象来调用)
- 并在一个体面的时间内处置它(如果你不会在Pocket Outlook中有奇怪的行为)
在使用Windows Mobile时,如果您不希望表单全屏,则需要将FormBorderStyle设置为None 。 如果你不这样做,那么你会花数小时抽出你的头发,想知道为什么它会自动调整到全屏尺寸(这实际上是Windows Mobile的一个function )