tag:blogger.com,1999:blog-388959592009-06-21T22:51:32.114ZSimon HartEverything mobile (and anything in-between) in the modern enterpriseSimon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.comBlogger186125tag:blogger.com,1999:blog-38895959.post-17679353604815916652009-06-18T21:49:00.002Z2009-06-18T21:51:50.840ZTechNet UK Virtual Conference 2009Another virtual conference will be taking place tomorrow (Friday 19th June) which is the TechNet UK Virtual Conference.<br /><br />Please find more information here: <a href="http://technet.microsoft.com/en-gb/dd819085.aspx">http://technet.microsoft.com/en-gb/dd819085.aspx</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-1767935360481591665?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-53065084768179499722009-06-14T08:05:00.007Z2009-06-14T09:56:11.886ZDbDataReader.DoesColumnExistHave you ever wanted to code something like the following:<pre>var dbCommand = Database.DbProviderFactory.CreateCommand();<br />dbCommand.CommandText = "select * from MyTable";<br />var reader = Database.ExecuteReader(dbCommand, null);<br />if (reader.Read())<br />{<br /> if (reader.DoesColumnExist("mycolumn")<br /> {<br /> //Then we know its safe to select the column.<br /> }<br />}</pre>You're probably thinking, why would I want to do that? well if you're building a generic data handler library and you don't know what columns have been selected but you know the columns that could be selected then it is very useful as using the indexer to return the data for the specified column will throw an exception if it doesn't exist.<br /><br />I thought this extension method solves this problem and would be useful for others:<pre>public static class DbDataReaderExtensions<br />{<br /> public static bool DoesColumnExist(this IDataReader reader, string column)<br /> {<br /> if (reader.IsNull()) throw new ArgumentNullException("reader");<br /> if (string.IsNullOrEmpty(column)) throw new ArgumentNullException("column");<br /> <br /> for (var i = 0; i < reader.FieldCount; i++)<br /> {<br /> if (reader.GetName(i).Equals(column))<br /> return true;<br /> }<br /> return false;<br /> }<br />}</pre>It's relatively straight forward but saves you from writing the same piece of code over and over again.<br /><br />The unit test class for this is as follows:<pre>[TestClass]<br />public class DataReaderExtensionsTests<br />{<br /> [TestMethod]<br /> public void ThrowsIfNullReaderIsPassed()<br /> {<br /> const MockDbDataReader reader = null;<br /> AssertExt.Throws<ArgumentNullException>(() => reader.DoesColumnExist("foo"));<br /> }<br /><br /> [TestMethod]<br /> public void ThrowsIfNullColumnIsPassed()<br /> {<br /> var reader = new MockDbDataReader();<br /> AssertExt.Throws<ArgumentNullException>(() => reader.DoesColumnExist(null));<br /> AssertExt.Throws<ArgumentNullException>(() => reader.DoesColumnExist(string.Empty));<br /> }<br /><br /> [TestMethod]<br /> public void ValidExists()<br /> {<br /> var reader = new MockDbDataReader();<br /> Assert.IsTrue(reader.DoesColumnExist("One"));<br /> Assert.IsTrue(reader.DoesColumnExist("Two"));<br /> Assert.IsTrue(reader.DoesColumnExist("Three"));<br /> Assert.IsTrue(reader.DoesColumnExist("Four"));<br /> Assert.IsTrue(reader.DoesColumnExist("Five"));<br /> }<br /><br /> [TestMethod]<br /> public void InvalidExists()<br /> {<br /> var reader = new MockDbDataReader();<br /> Assert.IsFalse(reader.DoesColumnExist("foo"));<br /> Assert.IsFalse(reader.DoesColumnExist("bar"));<br /> }<br />}</pre>You'll notice I have mocked the DbDataReader. Because there are mocking frameworks on the Compact Framework and probably will not be for some time (due to CF limitations) I have created a mocked class implementing the IDataReader interface. This mock class looks like the following:<pre>public class MockDbDataReader : IDataReader<br />{<br /> readonly Dictionary<int, string> getName = new Dictionary<int, string>();<br /> public MockDbDataReader()<br /> {<br /> getName.Add(0, "One");<br /> getName.Add(1, "Two");<br /> getName.Add(2, "Three");<br /> getName.Add(3, "Four");<br /> getName.Add(4, "Five");<br /> }<br /><br /> #region IDataReader Members<br /><br /> public void Close()<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public int Depth<br /> {<br /> get { throw new NotImplementedException(); }<br /> }<br /><br /> public DataTable GetSchemaTable()<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public bool IsClosed<br /> {<br /> get { throw new NotImplementedException(); }<br /> }<br /><br /> public bool NextResult()<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public bool Read()<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public int RecordsAffected<br /> {<br /> get { throw new NotImplementedException(); }<br /> }<br /><br /> #endregion<br /><br /> #region IDisposable Members<br /><br /> public void Dispose()<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> #endregion<br /><br /> #region IDataRecord Members<br /><br /> public int FieldCount<br /> {<br /> get { return 5; }<br /> }<br /><br /> public bool GetBoolean(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public byte GetByte(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public char GetChar(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public IDataReader GetData(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public string GetDataTypeName(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public DateTime GetDateTime(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public decimal GetDecimal(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public double GetDouble(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public Type GetFieldType(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public float GetFloat(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public Guid GetGuid(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public short GetInt16(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public int GetInt32(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public long GetInt64(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public string GetName(int i)<br /> {<br /> return getName.ContainsKey(i) ? getName[i] : string.Empty;<br /> }<br /><br /> public int GetOrdinal(string name)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public string GetString(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public object GetValue(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public int GetValues(object[] values)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public bool IsDBNull(int i)<br /> {<br /> throw new NotImplementedException();<br /> }<br /><br /> public object this[string name]<br /> {<br /> get { throw new NotImplementedException(); }<br /> }<br /><br /> public object this[int i]<br /> {<br /> get { throw new NotImplementedException(); }<br /> }<br /><br /> #endregion<br />}</pre>All we have done is returned 5 for the FieldCount, then provided some data so when GetName() is called we return the relevant item in the dictionary to resemble a real data reader object.<br /><br />We could have written an integration test but this is pointless as we know the DataReader class has been tested and works.<br /><br />The unit test class above gives 100% code coverage.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-5306508476817949972?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com2tag:blogger.com,1999:blog-38895959.post-14199660824468614032009-06-04T16:00:00.004Z2009-06-04T16:09:13.599ZJP Morgan Chase & Co. Corporate Challenge<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.jpmorganchasecc.com/images/jp_logo_right.gif"><img style="cursor: pointer; width: 177px; height: 186px;" src="http://www.jpmorganchasecc.com/images/jp_logo_right.gif" alt="" border="0" /></a><br /><br />Hitachi Consulting (including me) is participating in the JP Morgan Chase & Co. Corporate Challenge which is a world wide fundraising event in most major cities throughout the world.<br /><br />Hitachi Consulting's goal is to raise £1000 for the Down's Syndrome Association <span style="font-size: 11pt; font-family: "Calibri","sans-serif";"></span>and the challenge is a 6.5km run around Battersea park in London on the 9th July 2009.<br /><br />If you were feeling generious :) you can sponsor the us over at: <p class="MsoNormal"><a href="http://www.justgiving.com/hcukjpmorganchallenge2009" target="_blank">http://www.justgiving.com/hcukjpmorganchallenge2009</a></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-1419966082446861403?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-85244926681497267222009-05-23T09:08:00.005Z2009-05-23T09:13:54.538ZMicrosoft patterns & practices Summit 2009<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://i.msdn.microsoft.com/bb190332.3a%28en-us,MSDN.10%29.png"><img style="cursor: pointer; width: 249px; height: 64px;" src="http://i.msdn.microsoft.com/bb190332.3a%28en-us,MSDN.10%29.png" alt="" border="0" /></a><br /><br />Microsoft are hosting the patterns & practices Summit Oct 12th - 16th 2009 at the Microsoft Conference Centre on Microsoft Campus in Redmond, WA.<br /><br />To learn more about this event, see here: <a href="http://msdn.microsoft.com/en-us/practices/dd578307.aspx">http://msdn.microsoft.com/en-us/practices/dd578307.aspx</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-8524492668149726722?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-63331749282268915042009-05-09T10:47:00.006Z2009-05-09T14:03:38.800ZMicrosoft Architect Insight Conference May 8th 2009 Mobile Decks for download<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://i.msdn.microsoft.com/dd135209.header%28en-gb,MSDN.10%29.jpg"><img style="cursor: pointer; width: 1000px; height: 172px;" src="http://i.msdn.microsoft.com/dd135209.header%28en-gb,MSDN.10%29.jpg" alt="" border="0" /></a><br /><br />As promised to the delegates at the recent <a href="http://msdn.microsoft.com/en-gb/architecture/dd135209.aspx">Microsoft Architect Insight Conference</a> held on 8th May 2009 at Microsoft London Victoria, I have uploaded the decks from my breakout which was presented with Dave Baker from the Developer and Platform Group at Microsoft and my interactive session for download.<br /><br />The two decks were used in the sessions <span style="font-weight: bold;">Extending the Enterprise through Mobile</span> and <span style="font-weight: bold;">Mobile Implementation Patterns</span>. Please note: the interactive Mobile Implementation Patterns deck is very light and the session was very much a chalk and talk session. I opened it up for debate for just about anything mobile. This deck contains some information about Hitachi Consulting who we are, our clients we've worked with which may interest you.<br /><br />Thanks to Dave for giving a great session and also thanks to all the delegates in the interactive who made it a good discussion session.<br /><br />You can download the decks <a href="https://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=MobileAIC2009&ReleaseId=2650">here</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-6333174928226891504?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-13026525362818177652009-04-13T10:31:00.008Z2009-04-15T20:01:42.679ZCopying dependency files to the output directory when running unit tests with MSTestA rather long title don't you think :) But have you ever wanted to write a unit test using Visual Studio Test Edition and MSTest to have a dependency on configuration files other than app.config to fulfill your test?<br /><br />This post is mainly about test support for device testing but is the same for desktop testing too.<br /><br />Now, most people use <span style="font-family:courier new;">app.config</span> as a configuration file in .NET for desktop applications. On devices, <span style="font-family:courier new;">System.Configuration</span> is not supported. So some device developers end up writing there own configuration reader by serializing the XML into an object. Alternatively they use the class from OpenNETCF SDF or they might parse the XML using LINQ to XML or plain old System.Xml.<br /><br />Personally I tend to use the serialization option. My configuration files are not named <span style="font-family:courier new;">app.config</span> I tend to name them something more specific. You'll find Visual Studio or the test engine does not deploy any other file to the tests Output directory, even if you set properties <span style="font-family:courier new;">Build Action</span> to <span style="font-family:courier new;">Content</span> and <span style="font-family:courier new;">Copy to Output Directory</span> to <span style="font-family:courier new;">Copy always</span>. Running your test will fail if you have a dependency on the given configuration file as Visual Studio will not deploy the custom configuration file. It is highly likely most desktop developers have never seen this or unaware this limitation exists because most desktop devs use <span style="font-family:courier new;">app.config</span>. In most cases for desktop devs there is no problem.<br /><br />So how do device guys get around this problem? You can use the same technique as the Mobile p&p team do with the <span style="font-family:courier new;">DataAccess</span> block which forms part of the recent Mobile Application Blocks drop: <a href="http://www.codeplex.com/Mobile">http://www.codeplex.com/Mobile</a>. In one of there test projects they have a mock database dependency that is tested on the desktop but need a sample database to test against.<br />They set the <span style="font-family:courier new;">Build Action</span> to <span style="font-family:courier new;">Embedded Resource</span> then they use reflection to unpack it. You might think this is quite a bit of work, but they have a reusable class named <span style="font-family:courier new;">TestResourceFile</span> that belongs to the <span style="font-family:courier new;">TestUtilities</span> project. Using this class does all the unpacking for you.<br /><br />The code to copy this dependency could look like the following (I've taken this from the p&p Mobile codebase):<pre>private TestResourceFile CreateDbFile()<br />{<br /> dbFile = new TestResourceFile(this, "MockDatastore.sdf");<br /> connectionString = String.Format(connectionStringPattern, dbFile.Filename);<br /> return dbFile;<br />}<br /><br />[TestMethod]<br />public void ThrowsIfNullParameterNameIsPassed()<br />{<br /> using (TestResourceFile file = CreateDbFile())<br /> {<br /> using (Database database = new SqlDatabase(connectionString))<br /> {<br /> Database service = new SqlDatabase(connectionString);<br /> ExtendedAssert.Throws<argumentnullexception>(<br /> delegate { DbParameter param = service.CreateParameter(null, "Maria Anders"); });<br /> }<br /> }<br />}</argumentnullexception></pre>But even still there is a better way to solve this problem and that is to use the <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.deploymentitemattribute%28VS.80%29.aspx">DeploymentItemAttribute</a> class. It's use is simple. The following code illustrates it use:<pre>[DeploymentItem("Mobile.DataMapper.config")]<br />[TestClass]<br />public class DataContextFactoryTests<br />{<br />}</pre>The above code will copy the file "Mobile.DataMapper.config" to the test output directory. You need to ensure to set the file properties <span style="font-family: courier new;">Build Action</span> to <span style="font-family: courier new;">Content</span> and <span style="font-family: courier new;">Copy to Output Directory</span> to <span style="font-family: courier new;">Copy always</span>.<br /><br />I've got to say thanks to Chris Tacke for telling me about this attribute class.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-1302652536281817765?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com4tag:blogger.com,1999:blog-38895959.post-43459231582928399582009-04-12T14:25:00.004Z2009-04-12T15:01:16.429Zhttp://answers.microsoft.comMicrosoft has recently (last few months) announced and released a website for Windows Vista users to post questions here: <a href="http://answers.microsoft.com/">http://answers.microsoft.com.</a><br /><br />There is quite a large MVP presence there to answer your Windows Vista questions.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-4345923158292839958?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-13117596510894108922009-04-10T21:44:00.002Z2009-04-10T21:50:00.677ZWhat type of applications can we build on Windows Mobile today - Part 3 of 10This is part 3 of 10 of the <a href="http://www.simonrhart.com/2009/02/windows-mobile-development-for.html">getting started with Windows Mobile development series</a>. For previous posts in this series please see <a href="http://www.simonrhart.com/2009/02/windows-mobile-development-for.html">here</a>.<br /><br />Today mobile development is getting easier. Many folks from the desktop can port there C# skills over and hit the ground running fairly quickly. The Compact Framework is maturing nicely. Development tools and emulators are getting more feature rich and more reliable.<br /><br />The types of applications you can build today for Windows Mobile - with regards to managed code fall into the following groups:<br /><ol><li><span style="font-weight: bold;">Microsoft .NET Compact Framework</span>. This is a subset of the Microsoft .NET Frameworkdesigned specifically for mobile devices. Use this technology for mobile applications that must run on the device without guaranteed network connectivity. </li><li><span style="font-weight: bold;">ASP.NET Mobile</span>. This is a subset of ASP.NET, designed specifically for mobile devices. ASP.NET Mobile applications can be hosted on a normal ASP.NET server. Use this technology for mobile Web applications when you need to support a large number of mobile devices and browsers that can rely on a guaranteed network connection.<br /></li></ol><br />ASP.NET for Mobile no longer has designer support in Visual Studio 2008. You can simply use the desktop controls and they will render. Now with "6on6" which is IE 6 engine on Windows Mobile 6.1 this will make web development for mobile easier. You can test IE 6 with the recently released WM 6.1 emulators. I wrote a post on this here. One thing to bear in mind is of course screen size.<br /><br />Most developers write .NET Compact Framework applications over ASP.NET for LOB (Line of Business applications) due to the smart client nature. Also the power of a .NET CF application allows the developer to do whatever he wants. You can access the camera the GPS chipset the radio or the phone. You can access Outlook, manipulate appointments or add/change a contact. You can access a Relational Database Management system such as SQL Server Compact to store your applications data then sync back to SQL Server desktop using Sync Services (Sync Framework). You can write very compelling UI using GDI or on later devices GDI+ for support such as gradient backgrounds and transparency. XNA sadly is not supported, however DirectX is but is limited and memory intensive.<br /><br />The main power of using the .NET Compact Framework over any other technology is the fact that it is embedded and works great in smart client environments where connectivity is an issue.<br /><br />ASP.NET is rarely used in my experience, one reason is due to the connectivity issues. Under ASP.NET, mobile devices require a constant connection with the server in order for this type of architecture to work. Web applications do not work well in enterprise solutions for mobile devices. They do work well for consumer applications but not mission critical ones.<br /><br />You'll probably be thinking how do you architect an application for the .NET Compact Framework. Most developers adopt the Active record pattern for the business layer. This tends to work well as mobile applications tend not to be as complex as desktop applications. And now performance tends not to be so much of a problem as it once was. ORMs and Domain Driven Development with patterns such as the repository data access layer is not quite as good a story.<br /><br />The only ORM that supports the CF and SQL CE to date is LLBLGen. I am in the process of building an ORM for the Compact Framework and intend on writing an MSDN article how I did it.<br /><br />The CF 3.5 does support WCF as a consumer, ServiceHost is not supported. There are many binding and other limitations however. Usually the device will have its own domain that uses either a message protocol which can be completely bespoke over TCP or a service layer with standard DTOs via HTTP. Or in some cases Sync data directly using Sync Services or merge replication. Each application is different. Of course vanilla Web Services ASMX has been supported since CF 1.0.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-1311759651089410892?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-73534867129201098732009-04-06T21:46:00.003Z2009-04-06T21:50:09.322ZPreview of Windows Mobile 6.5 at MIXCheckout WM 6.5 by Loke Uei Tan (requires Silverlight). See other videos here: <a href="http://videos.visitmix.com/MIX09/All">http://videos.visitmix.com/MIX09/All</a><br /><br /><object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="960" height="540"><br /><param name="source" value="http://videos.visitmix.com/Skins/mixvideos/Styles/players/VideoPlayer2009_03_27.xap" /><br /><param name="initParams" value="m=http://mschannel9.vo.msecnd.net/o9/mix/09/wmv-hq/t61f.wmv,autostart=false,autohide=true,showembed=true, thumbnail=http://videos.visitmix.com/Skins/mixvideos/Styles/players/VideoPlayer2009_03_27.xap, postid=0" /><br /><param name="background" value="#00FFFFFF" /><br /><a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"><br /><img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/><br /></a><br /></object><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-7353486712920109873?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-26660338334095237892009-04-02T21:44:00.016Z2009-04-05T13:03:43.291ZAn example of the Plugin pattern on the Compact FrameworkI have been talking about IoC containers on the Compact Framework lately and thought I'd show an example of implementing a simpler example of separating concerns. There is another common pattern to which IoC I believe was derived called the Plugin pattern. <br /><br />The Plugin pattern is talked about by Martin Fowler in his Patterns Of Enterprise Application Architecture book (good book by the way). It is (in my opinion) a simpler solution to IoC but is a little more limited and doesn't usually involve a framework.<br /><br />I involves using reflection and creating a factory to create a type usually specified in a configuration file using a common interface. This pattern promotes <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">Aspect Oriented Programming</a>.<br /><br />As I am in the process of building a managed ORM for the Compact Framework, I decided to use the Plugin pattern for building the data context part of the API. I decided this because the Plugin is easy to implement and doesn't require any framework to implement. I wanted to keep the ORM as simple as possible while at the same time making the framework decoupled from the type of database desired.<br /><br />As mentioned I am using this pattern for the data context part of my ORM and I have a configuration file used to specify the type of database. Doing this enables me to easily change my database without having to rewrite a vast majority of my application. I don't even need to recompile my app. I can simply change the config and re-run my app.<br /><br />The configuration setting that specifies the database dialect looks like this:<pre><property name="datacontext" value="Mobile.DataMapper.Dialect.SqlServerCe35DataContext"/></pre>The SqlServerCe35DataContext looks like:<pre>public class SqlServerCe35DataContext : DataContext<br />{<br /> private SqlDatabase _database;<br /> private readonly MsSqlCe35Dialect _dialect;<br /><br /> public SqlServerCe35DataContext()<br /> {<br /> _dialect = new MsSqlCe35Dialect();<br /> }<br /><br /> internal override Database Database<br /> {<br /> get <br /> { <br /> if (_database == null) _database = new SqlDatabase(ConnectionString);<br /> return _database;<br /> }<br /> }<br /><br /> internal override Dialect Dialect<br /> {<br /> get { return _dialect; }<br /> }<br />}</pre>The DataContext class contains the default implementation of SQL Server CE and is defined as an abstract class. It also implements the IDataContext interface which we use in our factory. This enables us to use the Plugin pattern successfully. <br /><br />Part of the DataContext class looks like this:<pre>public abstract class DataContext : IDataContext<br />{<br /> private DbTransaction _transaction;<br /> private string _connectionString;<br /><br /> public virtual void Commit()<br /> {<br /> if (_transaction.IsNull()) throw new InvalidOperationException("There is no transaction for this session.");<br /> _transaction.Commit();<br /> }<br /><br /> public virtual void BeginTransaction()<br /> {<br /> _transaction = Database.GetConnection().BeginTransaction();<br /> }<br /><br /> public virtual void BeginTransaction(IsolationLevel isolationLevel)<br /> {<br /> _transaction = Database.GetConnection().BeginTransaction(isolationLevel);<br /> }<br /><br /> internal abstract Database Database<br /> { <br /> get;<br /> }<br /><br /> internal abstract Dialect Dialect<br /> {<br /> get;<br /> }<br />}<br /></pre>I've omitted many memebers as it's not important what this class does. What is important is the implementation in order to implement this pattern for devices.<br /><br />For those interested, this is based on the Mobile Client Software Factory. I will be publishing the source code to my ORM for Windows Mobile soon - once finished.<br /><br />So as we saw, the DataContext is abstract and it contains an interface. Just so you can see, the interface looks like this: <pre>public interface IDataContext : IDisposable<br />{<br /> string ConnectionString { get; set; }<br /><br /> //Transaction management.<br /> void Commit();<br /> void Rollback();<br /> bool IsInTransaction{ get;}<br /> void BeginTransaction();<br /> void BeginTransaction(IsolationLevel isolationLevel);<br /><br /> IList<TEntity> Read<TEntity>(QueryExpressionCollection queryExpressionCollection);<br /> IList<TEntity> Read<TEntity>(QueryExpressionCollection <br /> queryExpressionCollection, List<Func<ObjectProperty>> columnsInScope);<br /> IList<TEntity> FindAll<TEntity>();<br /> TEntity Read<TEntity>(object id);<br /><br /> int Delete<TEntity>(TEntity entity);<br /> TEntity Save<TEntity>(TEntity entity);<br /> string DatabaseName { get; set; }<br /> <br />}</pre>As I said I omitted most of the above members from the DataContext class above for clarity as I want to focus on the architecture not implementation details for this post.<br /><br />So now we have four things:<br /><br />1. Configuration file that tells us what datacontext to use.<br />2. The datacontext implementation (SQL CE Server) to use.<br />3. The base datacontext class.<br />4. The datacontext implementation.<br /><br />The only thing that is missing to put all this together so the consumer can just work with the interface (as the consumer doesn't care about where the data lives or how the data is retrieved) is the DataContextFactory.<br /><br />The Factory is very simple. It looks like this:<pre>public class DataContextFactory<br />{<br /> private IDataContext _instance;<br /><br /> public DataContextFactory()<br /> {<br /> CreateInstance(null);<br /> }<br /><br /> public DataContextFactory(IDataMapperConfiguration dataMapperConfiguration)<br /> {<br /> CreateInstance(dataMapperConfiguration);<br /> }<br /><br /> private void CreateInstance(IDataMapperConfiguration dataMapperConfiguration)<br /> {<br /> if (dataMapperConfiguration == null) <br /> dataMapperConfiguration = MapperFactory.CreateDataMapperConfiguration();<br /> var dataContext = dataMapperConfiguration.DataContext;<br /> var asm = Assembly.GetExecutingAssembly();<br /> _instance = (IDataContext)asm.CreateInstance(dataContext.Value);<br /> if (dataMapperConfiguration.HasConnectionString)<br /> _instance.ConnectionString = dataMapperConfiguration.ConnectionString.Value;<br /> }<br /><br /> public IDataContext GetDataContext<br /> {<br /> get<br /> {<br /> return _instance;<br /> }<br /> }<br />}</pre>Notice how we have another dependency the IDataMapperConfiguration. There's no need to document this code but quite simply it's a serialized object of the XML posted earlier. We get two things from this XML file 1. The ConnectionString and 2. The concrete DataContext class that implements DataContext. Notice how we set the ConnectionString property after the type has been created. We do this because the CF only supports one Assembly.CreateInstance method that accepts the type to create.<br /><br />So using this code from the consumer looks like this:<pre>IDataContext context = new DataContextFactory().GetDataContext;</pre>then the consumer can work with this interface as opposed to the implementation. The consumer knows nothing about the underlying database or storage. If you changed the database from Sql CE to SQLLite for example, it is a simple case of changing the configuration file, then re-running the app.<br /><br />You could implement this architecture with the IoC framework and using dependency injection pattern but the current one developed by the p&p team at Microsoft doesn't have support for configuration files. This means you'd have to recompile your app anytime you change the DataContext implementor. Now, no doubt Microsoft will roll out another version that supports configuration files in the future as the ContainerModel is a fairly early drop.<br /><br />So the benefit with this implementation is, it's really really easy to implement and doesn't require any framework. If the implementors existed in another assembly, you could easily change the DataContextFactory to use the LoadFrom method to load a given assembly.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-2666033833409523789?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-3503307570795986312009-04-01T18:43:00.009Z2009-04-19T10:25:43.470ZDependency injection using the ContainerModel on the Compact FrameworkI mentioned a few weeks ago about the availability of an IoC framework for the Compact Framework <a href="http://www.simonrhart.com/2009/03/ioc-framework-for-compact-framework.html">here</a>.<br /><br />But a question related to this is how do you implement the dependency injection pattern with this IoC framework as IoC (Inversion of Control) and dependency injection go hand in hand with one another.<br /><br />The most common way to implement dependency injection is via the constructor. Sadley this container doesn't work like Castle Windsor where Castle resolves dependencies for you automatically without you having to define then when registering the class. However the class still needs to be defined by an interface! With the device Container model you have to explicitly define your dependencies at registration. I'm ok with this as I'm happy to have a half decent container model for the Compact Framework.<br /><br />So we have our CustomerRepository class that has a dependency on some Adapter (I just made this adapter up, it could do anything). The class looks like this:<br /><pre>public class CustomerRepository : Repository<Customer, int>, ICustomerRepository<br />{<br /> private IAdapter _adapter;<br /><br /> public CustomerRepository(IAdapter adapter)<br /> {<br /> if (adapter.IsNull()) throw new ArgumentNullException("adapter");<br /> _adapter = adapter;<br /> }<br />}</pre>Now, there are no methods in this class but the point is to show the dependency because later, we want to use the adapter class to do some... adapting.<br /><br />So how do we set up the container to inject the adapter. Something like the following should do the trick:<pre>using Microsoft.Practices.Mobile.ContainerModel;</pre><pre>var builder = new ContainerBuilder();<br />builder.Register<IAdapter>(adapter => new Adapter());<br />builder.Register<ICustomerRepository>(repository => new CustomerRepository(Resolve<IAdapter>()));<br />builder.Build(container);</pre>Then from the consumer, we can code something like the following:<pre>var customerRepository = ComponentContainer.Resolve<ICustomerRepository>();</pre>We didn't have to declare our dependency, it was injected by the framework. We just resolved the adapter when we registered the repository. Of course you need to register this dependency with the framework first. You could use the concrete type here but this means if you change implementation details, you'd have to change the implementor in more than one place.<br /><br />There we have it, dependency injection using an IoC container on the Compact Framework 3.5.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-350330757079598631?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-60381786512531780872009-03-25T21:48:00.007Z2009-03-25T22:24:14.204ZMissing IEnumerable<T>.ForEach(Action<T> action)Have you ever wanted to code something like this in .NET 3.5:<pre>var repository = new CustomerRepository();<br />repository.Customers.ForEach(customer => Console.WriteLine(string.Format("Customer: {0} {1}", <br /> customer.FirstName, customer.LastName)));<br />Console.Read();</pre>Where Customers is of type Collection. Well you can't out of the box as the framework doesn't provide an extension for IEnumerable foreach (which is what Collection implements).<br /><br />The Repository and domain object in the above case looks like this:<pre>public class CustomerRepository<br />{<br /> public CustomerRepository()<br /> {<br /> Customers = new Collection<Customer>()<br /> {<br /> new Customer()<br /> {<br /> FirstName = "Simon",<br /> LastName = "Hart"<br /> },<br /> new Customer()<br /> {<br /> FirstName = "Joe",<br /> LastName = "Bloggs"<br /> }<br /> };<br /> }<br /><br /> public ICollection<Customer> Customers<br /> {<br /> get; set;<br /> }<br />}<br /><br />public class Customer<br />{<br /> public string FirstName<br /> { <br /> get; set;<br /> }<br /><br /> public string LastName<br /> { <br /> get; set;<br /> }<br />}</pre>You can make the above call work with this simple extension for IEnumerable:<pre>public static class GenericIEnumerableExtensions<br />{<br /> public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)<br /> {<br /> foreach (var item in collection)<br /> {<br /> action(item);<br /> }<br /> }<br />}</pre>It's quite simple in that it accepts one parameter, an Action delegate with one parameter - this could be extended to do whatever you want. Although the above is in line with the List.ForEach extension method.<br /><br />The benefit of this is it simply reads better with less code.<br /><br />You might find this library found on codeplex useful: <a href="http://extensionmethodsyay.codeplex.com/">http://extensionmethodsyay.codeplex.com/</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-6038178651253178087?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com2tag:blogger.com,1999:blog-38895959.post-49922214402881069742009-03-18T19:56:00.002Z2009-03-18T20:04:31.927ZMobile Application Architecture GuideThe p&p team at Microsoft has put together this document on Mobile Application Architecture best practice. You can find it here on codeplex: <a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19798">http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19798</a><br /><br />I am currently putting together a solution that I plan to write an MSDN document detailing many of these technologies referenced in the document - some of which do not exist for mobile devices. This solution contains all the cool new stuff like, object relational mapping, Inversion of control, dependency injection, crosscutting inteceptors, domain driven design and how to achieve this in a mobile application. The latest UI controls in the market place. The repository data pattern. .NET CF 3.5, LINQ and lambdas - when to use them. Test driven development using MSTEST for devices.<br /><br />I will post the link here when done.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-4992221440288106974?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-27979757829725797812009-03-17T22:06:00.003Z2009-03-17T22:13:23.361ZApple iPhone OS 3.0 preview eventA first look at the coming release of the Apple iPhone OS 3.0 by engadget: <a href="http://www.engadget.com/2009/03/17/live-from-apples-iphone-os-3-0-preview-event/">http://www.engadget.com/2009/03/17/live-from-apples-iphone-os-3-0-preview-event/</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-2797975782972579781?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-33259197535011495742009-03-09T21:33:00.004Z2009-03-09T21:48:19.606ZMicrosoft Recite Technology Preview<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://recite.microsoft.com/Images/common/logo.png"><img style="cursor: pointer; width: 300px; height: 106px;" src="http://recite.microsoft.com/Images/common/logo.png" alt="" border="0" /></a><br /><br />There is a lot of cool stuff coming out of Redmond lately and <a href="http://recite.microsoft.com/Pages/index.aspx">Microsoft Recite</a> is no exception.<br /><br />Microsoft Recite is a tool that allows you to verbally record your thoughts to aid you to remember things, then retrieve them by asking (voice recognition) Recite for the content using any of the phrases in the recorded message.<br /><br />Recite is supported on these devices:<br /><br /><div class="phoneThumbs"><span>AT&T BlackJack II</span></div> <div class="phoneThumbs"><span>AT&T Pantech Duo</span></div> <div class="phoneThumbs"><span>HTC Diamond<br /></span><div class="phoneThumbs"><span>Moto Q9m</span></div> <div class="phoneThumbs"><span>Palm Treo 800w</span></div> <div class="phoneThumbs"><span>Palm Treo Pro</span></div> <div class="phoneThumbs"><span>SMT 5800<br /></span><div class="phoneThumbs"><span>T-Mobile Dash</span></div> <div class="phoneThumbs"><span>T-Mobile Shadow</span></div> <div class="phoneThumbs"><span>T-Mobile Wing</span><br /></div></div></div> <div class="phoneThumbs"><span>Motorola Q9C</span></div><br /><br />Checkout a video of Recite in action here: <a href="http://recite.microsoft.com/Pages/ReciteVideo.aspx">http://recite.microsoft.com/Pages/ReciteVideo.aspx </a><br />Get it here: <a href="http://recite.microsoft.com/Pages/download.aspx">http://recite.microsoft.com/Pages/download.aspx</a><br /><br />I am unaware of any Recite managed SDK at this point.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-3325919753501149574?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-18702159342612342642009-03-09T21:18:00.003Z2009-03-09T21:23:28.202ZMicrosoft TechDays Developer 2009 - 24hr Virtual Event<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.msfttechdays.com/resources/template_files/Tech%20Days%20header%20white.jpg"><img style="cursor: pointer; width: 912px; height: 138px;" src="http://www.msfttechdays.com/resources/template_files/Tech%20Days%20header%20white.jpg" alt="" border="0" /></a><br /><br />On April 1st 2009, be part of Microsoft history and join developers all over the world for the first ever 24-hour day of technology learning.<br /><br />Participate in 95 live sessions anywhere, at anytime or on-demand at your convenience.<br /><br />It is a free event.<br /><br />To register for this event, click here: <a href="http://www.msfttechdays.com/public/home.aspx">http://www.msfttechdays.com/public/home.aspx</a><br /><br />To view the sessions, click here: <a href="http://www.msfttechdays.com/public/sessionlist.aspx">http://www.msfttechdays.com/public/sessionlist.aspx</a><br /><br />Microsoft are still calling for content so not all sessions are visible. Also you will be able to build you're own schedule in due course.<br /><br />I'm not aware of any mobility tracks as yet, but my best guess is there will be some.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-1870215934261234264?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-80667262957238995232009-03-09T13:11:00.002Z2009-04-19T10:26:03.890ZI'm a PC and I'm an MVP!The MVP version of the "I'm a PC" video (from the MVP summit 2009):<br /><br /><iframe src="http://www.microsoft.com/video/en/us/player/embed/6d53ed7b-f784-4c00-b145-3c1123debc40" allowtransparency="true" scrolling="no" width="430" frameborder="0" height="326"></iframe><br /><a href="http://www.microsoft.com/video/en/us/details/6d53ed7b-f784-4c00-b145-3c1123debc40?vp_evt=eref&vp_video=MVP+%22I%27m+a+PC%22+Video"></a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-8066726295723899523?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-34248599046815420632009-03-04T10:37:00.005Z2009-03-07T10:28:35.208ZBroadband Speed test - South East EnglandI recently changed ISPs for my home network. I now use O2 (in UK) O2 bought Be Un Limited a while back. I was on Sky - Sky bough Easynet a few years ago. Sky was very slow and unreliable.<br /><br />The upload bandwidth was almost no-existent. Experience playing on-line games was not much fun due to the lag. You need good upload bandwidth for playing on-line games successfully otherwise you just get slaughtered.<br /><br />I used h<a href="http://www.speedtest.net/">ttp://www.speedtest.net</a> to measure the speed of both networks. As you can see, it is a big difference between the two networks. Also notice the ping response differences.<br /><br />Anyone else in my area, Guildford, South East England who is on Sky should consider O2.<br /><br />Here are the results:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.speedtest.net/result/422644117.png"><img style="cursor: pointer; width: 300px; height: 135px;" src="http://www.speedtest.net/result/422644117.png" alt="" border="0" /></a><br />Sky Easynet (before)<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.speedtest.net/result/424649200.png"><img style="cursor: pointer; width: 300px; height: 135px;" src="http://www.speedtest.net/result/424649200.png" alt="" border="0" /></a><br />O2 (Be Un Limited)<br /><br />I am around 5 miles from the BT exchange.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-3424859904681542063?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-90435974460858270582009-03-03T22:38:00.007Z2009-03-09T23:00:17.915ZIoC framework for the Compact FrameworkAndy Wigley mentioned the other day the p&p team has released a series of blocks for the Compact Framework including a dependency injection framework called ContainerModel. So I decided to have a look.<br /><br />You can get the code from codeplex here: <a href="http://www.codeplex.com/Mobile">http://www.codeplex.com/Mobile</a><br /><br />It is based on the MCSF but for .NET CF 3.5.<br /><br />I have had a look at the IoC framework and it is pretty good but would be even better if it had support for configuration files (XML). So currently you have to code something like this:<pre>builder<br /> .Register<IEditCustomersView>(<br /> c => new EditCustomersView())<br /> .InitializedBy(<br /> (c, v) => v.Presenter = c.Resolve<EditCustomersPresenter>());</pre>Then you can code this:<pre>var view = ApplicationRoot.Container.Resolve<IEditCustomersView>();</pre>This is a first cut so maybe we will see support for configuration files in the future. If I get time I'll add support for it.<br /><br />It's quite cool as you can pass in an Action delegate at the time of register to instantiate the class.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-9043597446085827058?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com3tag:blogger.com,1999:blog-38895959.post-75768597702685581152009-02-24T20:34:00.002Z2009-02-24T20:52:57.076ZOracle Day 2009 - Smart Strategies for Uncertain Times<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.oracle.com/global/de/events/2009/local/uk/oracle_day/img/header.jpg"><img style="cursor: pointer; width: 900px; height: 212px;" src="http://www.oracle.com/global/de/events/2009/local/uk/oracle_day/img/header.jpg" alt="" border="0" /></a><br /><br /><br />On March 5th 2009 in London, Oracle is holding an event <a href="http://www.oracle.com/global/de/events/2009/local/uk/oracle_day/index.html">"Oracle 2009 - Smart Strategies for Uncertain Times"</a> to which Edenbrook is a key sponsor. A snip from the event website:<br /><br /><span style="font-style: italic;">The Oracle Day 2009 will cover the Oracle Technology stack from the Database and Middleware through to SOA, Enterprise 2.0, Business Intelligence and Security. This event will bring together IT professionals across industry sectors to address the real challenges faced by IT today - consolidating, cutting costs and innovating. After the keynote speaker presentations the event will break into two distinct tracks, one for </span><strong style="font-style: italic;">IT Management</strong><span style="font-style: italic;"> and one for </span><strong style="font-style: italic;">IT professionals</strong><span style="font-style: italic;"> and </span><strong style="font-style: italic;">architects</strong><span style="font-style: italic;">, providing the opportunity to select the sessions most relevant to you.<br /><br /><span style="font-style: italic;"><span style="font-style: italic;"><span style="font-style: italic;"></span></span></span></span>The address for this event is:<br /><p class="bodycopy">Renaissance Chancery Court Hotel<br />252 High Holborn <br />London<br />WC1V 7EN</p>To register <a href="http://www.oracle.com/webapps/events/EventsDetail.jsp?p_eventId=88773&src=6646846&src=6646846&Act=69">see here</a> or <a href="http://www.oracle.com/global/de/events/2009/local/uk/oracle_day/index.html">see here</a> for more information.<br /><p class="bodycopy"><br /></p><p class="bodycopy"><br /></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-7576859770268558115?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-5575330022696506642009-02-05T20:36:00.021Z2009-04-10T21:52:37.245ZMobility developer tools - Part 2 of 10<span style="font-weight: bold;">UPDATE:</span> updated 15/02/09 to correct some information.<br /><br />This is part 2 of 10 of the <a href="http://www.simonrhart.com/2009/02/windows-mobile-development-for.html">getting started with Windows Mobile development series</a>. For previous posts in this series, please see <a href="http://www.simonrhart.com/2009/02/windows-mobile-development-for.html">here</a>.<br /><br />Again we are concentrating mainly on Microsoft Windows Mobile technology although other developer tools are briefly mentioned.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Unmanaged Device Development</span></span><br /><br />Unmanaged device development is supported but not under Visual Studio 2008. Porting MFC code to Windows Mobile is not easy as there is no support for OLE on Windows CE. There is support for COM on Windows CE however.<br /><br /><span style="font-weight: bold;font-size:180%;" >Managed Device Development<br /><br /></span>The most common method for writing device applications today is using managed code. C# or VB.NET are the only supported managed languages for the Compact Framework. Very few people build applications using embedded technologies today. The sort of people doing embedded (native) development today are people who are writing low-level device driver software or managed developers who want to implement some sort of security code protection algorithm which can’t easily be reversed engineered as a managed application can.<br /><br />All versions of Visual Studio 2002 had support for managed device application development. This changed from VS 2003 where the express edition dropped managed device support and this was true for VS 2005 as well. So Standard Editions or later of VS 2003 or VS 2005 are required in order to target devices. This changed again with the release of the latest version of Visual Studio which is 2008 where Professional Edition or later is required for device application development support.<br /><br />VS2008 supports multi-targeting that allows the device developer to target CF 2.0 and CF 3.5. In order to target CF 1.0 you have to use VS 2005 with a CF 1.0 project. The Compact Framework is covered in great detail in a later relevant section.<br /><br />When installing Visual Studio 2008, the Smart Client extensions are selected by default but prior versions you have to explicitly select the Smart Client extensions for Mobile device support.<br /><br /><span style="font-weight: bold;font-size:180%;" >What is the Compact Framework</span><br /><br />The Compact Framework is a subset of the full Microsoft .NET Framework (not to be confused with the .NET Micro Framework which has a 300k memory footprint). Because device applications run on memory and CPU constrained devices, not all the classes, methods, properties etc are supported on the CF. There is a lot of stuff missing.<br /><br />The Compact Framework has around a 3-4 Mb memory footprint although with each release this gets larger to satisfy developers needs and new technology but devices are shipping with more and more memory (ROM and RAM) each year.<br /><br />Since Windows Mobile 2003 Second Edition, Microsoft has insisted that at the time the OEM builds the WM image, the latest RTM version of the Compact Framework is shipped in ROM. This is really cool for many reasons:<br /><ol><li>This gives a developer more RAM for his/her applications and also more flash storage</li><li>Before WM5 was released, there was no flash persistent storage that the OS occupied. Back then, everything resided in RAM and memory was divided between application storage space and proper RAM used to load applications. Performance was a nightmare as you can imagine. The user could customize this divide, but this was too complex for a non-technical user. So if the battery went flat, you would lose all your content. WM5 changed this. So Microsoft decided to ship the CF in ROM. This elevated some of the memory constraints but often the CF was out of date at the time of build because of the long process carriers/OEMs take to build new images they are not agile enough like Microsoft so by the time the devices hit the market, they are a version behind.</li><li>As it happens, WM2003 SE shipped with version 1 of the CF, which mean’t managed developers could for the first time write an auto load application and ship it on a removable flash card such as a SD or Micro SD card. So when card was inserted into the device the application would run. Previous to this managed developers had to write this kind of auto load application in eVC++ or eVB. The later WM5 devices shipped with the CF 2.0 SP1. Even many WM6.0 devices still ship today with CF 2.0 SP1 even though CF 3.5 has been released for over 1 year. It turns out WM6.1 do ship with CF 3.5 and SQL Compact 3.0 (latest version of SQL Compact at the time of writing is 3.5)<br /></li></ol><span style="font-weight: bold;font-size:180%;" >Compact Framework – Architectural differences over the desktop version</span><br /><br />There are some architectural differences with the Compact Framework over the desktop versions. There was no v1.1 or v3.0 of the CF. The latest version of the CF which is 3.5 has its own CLR. It’s not derived from the CF 2.0 as per the desktop. There is no *current* support for vector based UI such as WPF other than Silverlight 2 for Mobile (not even in CTP yet) – which we talk about in a later article. There is WCF client support in CF3.5 just no ServiceHost support. The WCF support is also a subset. The subset support is documented <a href="http://msdn.microsoft.com/en-us/library/bb397842.aspx">here</a> and <a href="http://blogs.msdn.com/andrewarnottms/archive/2007/08/21/the-wcf-subset-supported-by-netcf.aspx">here</a>.<br /><br />The Compact Framework is Retargetable – which means it supports and does define the AssemblyFlags(AssemblyNameFlags.Retargetable) attribute in all it’s assemblies. So what does this mean? Well it means you can retarget the IL compiled against the CF and run it against the desktop CLR (within reason) and generate the same native code. It saves you the need to recompile for the desktop.<br /><br />Below is a snapshot of the System.Windows.Forms assembly, as you can see the Retargetable enum is defined with the AssemblyFlags attribute.<br /><br /><p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >// Assembly <b>System.Windows.Forms</b>, Version 3.5.0.0</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" ></span> </p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.Reflection.AssemblyVersionAttribute.AssemblyVersionAttribute(string);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Reflection.AssemblyVersionAttribute/.ctor%28String%29"><span style=";font-family:'Courier New';font-size:10;" >AssemblyVersion</span></a><span style=";font-family:'Courier New';font-size:10;" >(<span style="color:maroon;">"3.5.0.0"</span>)]</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.Reflection.AssemblyFlagsAttribute.AssemblyFlagsAttribute(AssemblyNameFlags);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Reflection.AssemblyFlagsAttribute/.ctor%28System.Reflection.AssemblyNameFlags%29"><span style=";font-family:'Courier New';font-size:10;" >AssemblyFlags</span></a><span style=";font-family:'Courier New';font-size:10;" >(</span><a title="System.Reflection.AssemblyNameFlags" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Reflection.AssemblyNameFlags"><span style=";font-family:'Courier New';font-size:10;" >AssemblyNameFlags</span></a><span style=";font-family:'Courier New';font-size:10;" >.</span><a title="AssemblyNameFlags System.Reflection.AssemblyNameFlags.Retargetable;" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Reflection.AssemblyNameFlags/Retargetable"><span style=";font-family:'Courier New';font-size:10;" >Retargetable</span></a><span style=";font-family:'Courier New';font-size:10;" > | </span><a title="System.Reflection.AssemblyNameFlags" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Reflection.AssemblyNameFlags"><span style=";font-family:'Courier New';font-size:10;" >AssemblyNameFlags</span></a><span style=";font-family:'Courier New';font-size:10;" >.</span><a title="AssemblyNameFlags System.Reflection.AssemblyNameFlags.PublicKey;" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Reflection.AssemblyNameFlags/PublicKey"><span style=";font-family:'Courier New';font-size:10;" >PublicKey</span></a><span style=";font-family:'Courier New';font-size:10;" >)]</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.Resources.SatelliteContractVersionAttribute.SatelliteContractVersionAttribute(string);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Resources.SatelliteContractVersionAttribute/.ctor%28String%29"><span style=";font-family:'Courier New';font-size:10;" >SatelliteContractVersion</span></a><span style=";font-family:'Courier New';font-size:10;" >(<span style="color:maroon;">"3.5.0.0"</span>)]</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.CLSCompliantAttribute.CLSCompliantAttribute(bool);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.CLSCompliantAttribute/.ctor%28Boolean%29"><span style=";font-family:'Courier New';font-size:10;" >CLSCompliant</span></a><span style=";font-family:'Courier New';font-size:10;" >(<span style="color:maroon;">true</span>)]</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.Runtime.InteropServices.ComVisibleAttribute.ComVisibleAttribute(bool);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Runtime.InteropServices.ComVisibleAttribute/.ctor%28Boolean%29"><span style=";font-family:'Courier New';font-size:10;" >ComVisible</span></a><span style=";font-family:'Courier New';font-size:10;" >(<span style="color:maroon;">false</span>)]</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.Runtime.CompilerServices.InternalsVisibleToAttribute.InternalsVisibleToAttribute(string);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Runtime.CompilerServices.InternalsVisibleToAttribute/.ctor%28String%29"><span style=";font-family:'Courier New';font-size:10;" >InternalsVisibleTo</span></a><span style=";font-family:'Courier New';font-size:10;" >(<span style="color:maroon;">"Microsoft.WindowsCE.Forms,PublicKey=0024000004800000940000000602000000240000525341310004</span></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" ><span style="color:maroon;">000001000100bd1c7c2c1fbccfb3d24f1df7837e334e7686556e90dae8768b959497f308652686d8bebb7fc14eeb</span></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" ><span style="color:maroon;">efcfa9cffbf97d522fc678a5091cf188af5f3044b05fc3737b1c732fae4e191307da9fe29bda9c7d77e49dda0e5ed3</span></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" ><span style="color:maroon;">616b50f1e4d0a4b95fcd627157449e79cae5c5be456aa379849bd6dee7db0d5b0ff0743b0cabfa8ee7"</span>)]</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; vertical-align: top; line-height: normal;"><span style=";font-family:'Courier New';font-size:10;" >[<span style="color: rgb(16, 0, 160);">assembly:</span> </span><a title="System.Diagnostics.DebuggableAttribute.DebuggableAttribute(DebuggableAttribute.DebuggingModes);" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Diagnostics.DebuggableAttribute/.ctor%28System.Diagnostics.DebuggableAttribute.DebuggingModes%29"><span style=";font-family:'Courier New';font-size:10;" >Debuggable</span></a><span style=";font-family:'Courier New';font-size:10;" >(</span><a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Diagnostics.DebuggableAttribute"><span style=";font-family:'Courier New';font-size:10;" >DebuggableAttribute</span></a><span style=";font-family:'Courier New';font-size:10;" >.</span><a title="System.Diagnostics.DebuggableAttribute+DebuggingModes" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Diagnostics.DebuggableAttribute.DebuggingModes"><span style=";font-family:'Courier New';font-size:10;" >DebuggingModes</span></a><span style=";font-family:'Courier New';font-size:10;" >.</span><a title="DebuggableAttribute.DebuggingModes System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints;" href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:3.5.0.0:969db8053d3322ac/System.Diagnostics.DebuggableAttribute.DebuggingModes/IgnoreSymbolStoreSequencePoints"><span style=";font-family:'Courier New';font-size:10;" >IgnoreSymbolStoreSequencePoints</span></a><span style=";font-family:'Courier New';font-size:10;" >)]</span><b><span style=";font-family:'Verdana','sans-serif';font-size:13;color:black;" ></span></b></p><br />Although it is possible to share your device compiled with the desktop, the reverse is not true. This is because….you guessed it the desktop assemblies do not contain the Retargetable enum.<br /><br />Usually though, device developers share code, not assemblies, and have separate projects for the desktop and the device. Then in the code they will define a conditional compiler directive so that device specific instructions, for example calling coredll.dll functions are omitted on the desktop.<br /><br />Although the Compact Framework and the full framework use what appears to be the same classes, methods, properties. They both use the same languages C# or VB.NET and the CLR appears to be the same – at least from the outside. The Compact Framework’s CLR is dramatically different from that of the full framework especially from a memory GC and allocation perspective. This is largely to do with the way Windows CE handles memory. Each process, this includes each AppDomain is allocated a maximum of 32 meg. This doesn’t include the System core space. So of course the CF has to work with this constraint and there are many things it does to ensure the smooth running of applications and the general OS to ensure it doesn’t grind to a hault and run out of memory. I have written a fairly lengthy article about this process <a href="http://www.simonrhart.com/2008/05/memory-management-on-windows-mobile-61.html">here</a>.<br /><br /><span style="font-weight: bold;font-size:180%;" >Platform Invocation</span><br /><br />Because the Compact Framework is just that, compact it is inevitable that you have to call native code (OS Win32 APIs). This process is known as Platform Invocation or P/Invoke and thankfully it is supported on the CF.<br /><br />Just one example of this is controlling the Telephony API (TAPI) there is no managed API to control the radio, GSM, 3G etc. So it is often beneficial for managed device developers to have a background in native C++ as it requires translation to managed code for interop.<br /><br />There is a good site for doing interop between .NET and native here: <a href="http://www.pinvoke.net/">http://www.pinvoke.net</a>.<br /><br /><span style="font-weight: bold;font-size:180%;" >Device Emulators</span><br /><br />Device emulators available today are true ARM emulators and they come with the relevant Windows Mobile SDKs. So for example the latest version is Windows Mobile 6.1 SDK for Windows Mobile standard and professional. See the earlier post: <a href="http://www.simonrhart.com/2009/02/windows-ce-pocket-pc-smartphone-windows.html">Windows CE, Pocket PC, Smartphone, Windows Mobile - what's the difference! - Part 1 of 10</a> as to what the differences are between standard and professional. Pre Windows Mobile 5 emulators were based on x86 so were not really a true emulation. So back then developers never really used the emulators.<br /><br />Today they have come along way.<br /><br />Since Windows Mobile SDK 6 we have had the <a href="http://msdn.microsoft.com/en-us/library/bb158495.aspx">Cellular Emulator</a> that allows greater human testing.<br /><br /><span style="font-weight: bold;font-size:180%;" >OpenNETCF SDF</span><br /><br />OpenNETCF Smart Device Framework is a shared source project free for developers to download in a pre-compiled format.<br /><br />The SDF has been around for many years and was a life-line for developers when the CF v1.0 was released. This was because there were so many features/classes missing which made device developers used to developing desktop applications very difficult.<br /><br />So what is the SDF? The SDF is a series of class libraries to bridge the gap between the full framework and the Compact Framework. The OpenNETCF team identified the missing assemblies and in many cases wrote these for which now forms the SDF. The SDF also contains many device specific classes many of which form wrappers around native APIs that are absent from the CF and also include many UI controls. Even with the lastest version of the CF many featuers are still missing due to memory contraints, the SDF does in many cases offer an alternative solution.<br /><br />The community edition is free in pre-compiled format. The standard or professional editions are required if you want support - for a small fee.<br /><br />Please see the following link for more information:<br /><a href="http://www.opennetcf.com/">http://www.opennetcf.com</a>.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">ORMs on Windows CE</span></span><br /><br />There is currently no support for NHibernate or the Entity Framework or even DLINQ (LINQ to SQL) on Windows CE and the Compact Framework. There is however support for LLBLGen but often performance becomes a bottleneck for ORMs to work effectively.<br /><br />Most device developers handcraft data access layers themselves with a repository and domain model or a more <a href="http://en.wikipedia.org/wiki/Active_record_pattern">Active record pattern</a> approach.<br /><br />I am currently working on building a simplified ORM for the CF. It is tailored for the CF 3.5. It doesn't include any type of lazy loading or using proxies not because of the technical challenges this will impose but because the performance would a major issue on devices. I have designed it to support persistence ignorance objects or the support for Plain Old CLR Objects. It is built on the Mobile Client Software Factory Data Access Application block. I want to find a way to abstract the repository interface from the implementation as the <a href="http://www.castleproject.org/">Castle project</a> does. Currently the repository interface is tied to the implementor.<br /><br />I'll post this code on MSDN once finished.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">LINQ for devices</span></span><br /><br />There is support for LINQ on the Compact Framework. However there is no support for LINQ to Entities or DLINQ (LINQ to SQL). There is support for LINQ to XML.<br /><br />I've written a few posts about LINQ for devices <a href="http://www.simonrhart.com/search/label/LINQ">here</a>.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Databases on Windows CE</span></span><br /><br />There are a few options of relational database management systems when it comes to mobility. The options are as follows:<br /><ol><li><a href="http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx">SQL Server Compact</a></li><li><a href="http://www.sybase.com/ianywhere">Sybase IAnywhere</a></li><li><a href="http://www.sqlite.org/">SQLite</a></li><li><a href="http://www.mysql.com/">MySQL</a><br /></li></ol><br />Microsoft’s latest offering is SQL Server Compact 3.5. As with the Windows Mobile OS name changes, SQL Server Compact has gone down a similar path. The difference with SQL Server Compact today is that it can be run on the desktop as well as mobile devices. There are different installations but you can read/write the same database on both platforms. This feature has been supported since v3.1.<br /><br />There is support in SQL Server Management Studio (standard or later, not express) that allows you to connect to an SDF (compact database). The database looks as if it were a normal MDF desktop database. You can run queries, change the schema, create a diagram etc. The tool also has support to connect to a database on the device when the device is connected via ActiveSync or Device Manager (Vista). Note though, SQL Server 2005 Management Studio doesn’t work with SQL Server Compact 3.5. You have to have SQL Server 2008 installed. You can however use Visual Studio 2008 to connect to the SDF if you wish, although the tooling is very limited.<br /><br />The Microsoft Patterns & practices team have written a data application block that allows easy data access. This application block forms part of the Mobile Client Software Factory.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">SQL Server Compact – Architecture differences over the desktop version</span></span><br /><br />The main difference between SQL Server Compact and the full desktop version is SQL Server Compact is embedded. It runs within the callers context. This explains the reason why there is no support for stored procedures in SQL CE. This doesn’t mean the whole database engine is reloaded per application domain or process space. The process is shared across many applications as the system core memory space is used.<br /><br />Since version 3, SQL CE is now multi-threaded so it has multi-user support. As with most device technologies, SQL CE is a cut-down version of the desktop version. It wasn’t until v3.5 recently released that the rowversion (timestamp on desktop version) data type was supported.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">My Mobiler</span></span><br /><br />My mobiler is a tool that allows remote control of your device over ActiveSync or Sync Center. This is great for demos. I blogged about this tool a while back here: <a href="http://www.simonrhart.com/2008/06/my-mobiler.html">http://www.simonrhart.com/2008/06/my-mobiler.html.</a><br /><br />You'll notice it is very similar to <a href="http://www.simonrhart.com/2008/05/activesyncremotedisplay.html">ActiveSync remote display</a> but alot better. ActiveSync remote display comes with <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=74473fd6-1dcc-47aa-ab28-6a2b006edfe9&DisplayLang=en">Windows Mobile Power Toys</a>.<br /><br />Although to get it to work on later devices you'll need to read <a href="http://www.simonrhart.com/2008/05/activesyncremotedisplay.html">this</a>.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Windows Mobile Power Toys</span></span><br /><br /><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=74473fd6-1dcc-47aa-ab28-6a2b006edfe9&DisplayLang=en">Windows Mobile Power Toys</a> is a suite of applications to aid development. One of the most useful applications that comes with this suite is the Hopper - a user input stress simulator.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Windows Mobile API Usages Tool</span></span><br /><br />The <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fc803c7b-e855-475a-b8f3-38c19a007d36&displaylang=en">Windows Mobile API Usages Tool</a> is a command-line tool that runs on your desktop that performs static analysis of applications and binaries to run on Windows Mobile devices and reports the usage of system APIs and other resources. The goal of the tool is to provide a report of system dependencies to the application developer, optionally including the deprecated APIs that the application may currently depend on.<br /><br />The Windows Mobile team blog talk about this tool in a little bit of detail <a href="http://blogs.msdn.com/windowsmobile/archive/2008/08/04/introducing-the-windows-mobile-api-usage-tool.aspx">here</a>.<br /><table dir="ltr" width="100%" border="0" cellpadding="0" cellspacing="0"><tbody><tr valign="top"><td dir="ltr" width="100%"><br /></td></tr></tbody></table><span style="font-size:180%;"><span style="font-weight: bold;">Non-Microsoft Mobility Development</span></span><br /><br />Recently the Google Android was released. The developer tools are freely available to download. The development environment is called Eclipse (Java based) and the Google Android SDK contains the emulators to test your code.<br /><br />If you are interested in writing applications for Google Android, see here: <a href="http://code.google.com/andriod">http://code.google.com/android/ </a><br /><br />Currently you will not get the same development experience with Google Android than you do with Windows Mobile. Developing applications for mobile phones is challenging and Google Android is still yet to mature somewhat.<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Summary</span></span><br /><br />There are probably more tools that I have forgotten about but when I remember, I'll add them.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-557533002269650664?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com3tag:blogger.com,1999:blog-38895959.post-40906239078689988632009-02-01T21:56:00.009Z2009-04-10T21:55:21.261ZWindows Mobile Development - for newcommers<div> This post details the internal links for 10 getting started with Windows Mobile articles in the following order parts that are designed for newcomers to mobility. The links will become enabled once published:<br /></div> <ul><li><a class="ms-wikilink" href="http://www.simonrhart.com/2009/02/windows-ce-pocket-pc-smartphone-windows.html">Windows CE, Pocket PC, Smartphone, Windows Mobile - what's the difference! - Part 1 of 10</a> </li><li><a href="http://www.simonrhart.com/2009/02/mobility-developer-tools-part-2-of-10.html"><span class="ms-wikilink">Mobility developer tools - Part 2 of 10</span></a> </li><li><a href="http://www.simonrhart.com/2009/04/what-type-of-applications-can-we-build.html"><span class="ms-wikilink">What type of applications can we build on Windows Mobile today - Part 3 of 10</span></a> </li><li>Data storage and synchronization techniques on Windows Mobile - Part 4 of 10 </li><li>Unit testing and debugging on Windows Mobile - Part 5 of 10 </li><li>What is a smart client app and how do we develop a smart client app on WinMo? - Part 6 of 10 </li><li>Communications with Windows Mobile - What are our options - Part 7 of 10 </li><li>Silverlight and Windows Mobile - whats the story - Part 8 of 10 </li><li>The future of Windows Mobile - Part 9 of 10 </li><li>Our first Compact Framework 3.5 Windows Mobile application - Part 10 of 10</li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-4090623907868998863?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-72823107155004160582009-02-01T21:48:00.006Z2009-04-10T21:56:18.731ZWindows CE, Pocket PC, Smartphone, Windows Mobile - what's the difference! - Part 1 of 10<div class="ExternalClass7063FD044B9E40578C479292C76E3865">Welcome. This is the first part of 10 articles to get you <a href="http://www.simonrhart.com/2009/02/windows-mobile-development-for.html">introduced to Windows Mobile (device) development</a>. For other posts in this series, please see <a href="http://www.simonrhart.com/2009/02/windows-mobile-development-for.html">here</a>.<br /><br /></div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"> </div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865">The first question many new comers ask is, what is the difference between Windows CE, Windows Mobile, Pocket PC, Pocket PC Phone Edition, Smartphone, PDA's ? ....There are more names.</div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"> </div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865">Essentially this is Microsoft marketing gone mad! The truth is, <strong>all</strong> the platforms above are Windows CE.<br /><br /></div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"> </div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Windows CE</span></strong></div> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">Windows CE is an embedded operating system designed to run on small memory and CPU contrained devices. The OS is highly customizable. An OEM (original equipment manufacturer) can choose which bits to add and which bits to take away. </p> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">Some ISV's (independent software vendors) build their own Windows CE using a tool called Platform Builder to provision to a generic Windows CE device. Doing this allows great control over how the device will operate. This is known as Windows CE Embedded.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Pocket PC</span></strong></div> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">Pocket PC 2000 or PPC (Windows CE 3.0) was the first Pocket PC which didn't contain any GSM or radio. These are the devices you can still buy today except they are now called <strong>Windows Mobile Classic </strong>and most now are based on Windows CE 5.0. These devices were initally released with a 320x240 QVGA screen or 92DPI. So we mentioned Pocket PC is a Windows CE device. </p> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">Pocket PC/Windows Mobile devices have a different shell and a whole bunch of additional Win32 APIs and applications not seen on generic WinCE. So fundementally WinMo is a WinCE but a greatly customized version of it. The OEMs/carriers decide how the WinMo will be built, even down to what APIs are available to appliation developers and the security policy employed.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Smartphone</span></strong></div> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">First released in 2001. The Smartphone followed the PPC that added GSM support but unlike the PPC, it didn't have a touch screen and still doesn't today. Today the Smartphone is known as the <strong>Windows Mobile Standard </strong>edition. It's worth noting that the smartphone has a much smaller screen than the Pocket PC which at the time was 176x220 QVGA - which by and large hasn't really changed much. Hi-resolution smartphone devices are rare unlike its bigger brother PPC.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Pocket PC Phone Edition</span></strong></div> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">First released in 2002 (based on CE 4.1) which included GSM support with 2.5G (GPRS). Eassentially this was very similar to the Pocket PC except for radio. At the time there were very few of these devices around. Today it's hard to by a regular PPC (Windows Mobile Standard) device.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Windows Mobile 2003 Second Edition</span></strong></div> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">Released in 2003 and based on CE 4.2. Contained many shell extensions - a whole UI overhaul and also the .NET Compact Framework v1.0 included in ROM which was a major benefit for managed developers for lots of reasons, the main one being it was able to write a managed app to load from a flash card on a cold boot (hard reset). Notice the naming change. This was when "Windows Mobile" replaced Pocket PC. But just to confuse the matter, the Smartphone was kept.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Windows CE 5.0</span></strong></div> <p class="ExternalClass7063FD044B9E40578C479292C76E3865">Released in 2004, but it wasn't until 2005 when Windows Mobile 5.0 devices became available from carriers and OEMs. WM 5.0 release was also when the naming changed to the following:</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"> <ul><li><strong>Windows Mobile Classic </strong>(touch) would become - Pocket PC </li><li><strong>Windows Mobile Standard </strong>(non-touch) would become - Smartphone </li><li><strong>Windows Mobile Profesional </strong>(touch) would become - Pocket PC Phone Edition/Windows Mobile 2003</li></ul></div> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Windows Mobile 5</span></strong></div> <p>This was a major release for Microsoft from a platform perspective and developer story perspective. This was when Visual Studio 2005 with the .NET Compact Framework 2.0 was released which contained many many enhancements. Some of the great features from a platform perspective were an intermediate GPS driver which allowed developers to code against an API to get GPS data. Previously developers had to write very low level code to parse <a href="http://www.gpsinformation.org/dale/nmea.htm#nmea">NMEA sentenses</a> from a serial port (bluetooth or infrared) which was painful. In addition only one application could open the port and read data at anyone time. </p> <p>Previous to WM5.0 there was no support for an embedded GPS chipset. Another cool feature was a standard Microsoft stack for communicating with the devices camera. Previously you had to code against the OEM's SDK which changed from device to device. A new flash file system was employed so files didn't exist in RAM taking up valuable memory so enabling a persistent store for all files. Some of the later devices included the .NET CF 2.0. Of course support for C# 2.0 was a massive benefit for the managed developer. The new security model was also introduced in this released - a requirement from the carriers which has caused major pain for ISV's and developers. This is not going away, sadly.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">Windows Mobile 6.0/6.1</span></strong></div> <p>Windows Mobile 6.0 was released in 2007 and 6.1 in 2008. In fact I was in Redmond when 6.1 was released in April. Many enhancements and as more and more devices are released the uptake of VGA screens (initially supported from WM5.0) are becoming more common. Now also support for WVGA screens (640x800) is becoming popular - the new X1 from Sony and the HTC Touch Pro both support these displays. It is also worth mentioning here that WM6.1 is still based on Windows CE 5.0. It's simply shell extensions that have been added. Mainly the look and feel among other things. One thing is for sure, the performance is greatly improved over WM5.0.</p> <div class="ExternalClass7063FD044B9E40578C479292C76E3865"><strong><span style="font-size:180%;">References</span></strong></div> <p>See here for the Windows Mobile 5.0/6.0/6.1 SKU matrix: <a href="http://www.microsoft.com/windowsmobile/en-us/meet/version-compare.mspx">http://www.microsoft.com/windowsmobile/en-us/meet/version-compare.mspx</a></p> <p>Although this post has been primarilly about Microsoft device development, in a future post I will talk about other platforms and languages/developer tools such as the iPhone, the Google Android and the Symbian OS.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-7282310715500416058?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com4tag:blogger.com,1999:blog-38895959.post-1148354278311499632009-01-31T12:47:00.002Z2009-01-31T12:55:40.288ZProgrammatically saving a Microsoft CRM FormTo force Microsoft CRM to save the contents of a custom CRM form you can use the following javascript:<pre>crmForm.Save();</pre>Note this only saves data within CRM not data within your IFrame.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-114835427831149963?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0tag:blogger.com,1999:blog-38895959.post-7493125788195560512009-01-31T12:26:00.002Z2009-01-31T12:38:37.701ZMaximizing a customized form in Microsoft CRMSometimes it's desirable to maximize your CRM customized form so more screen is visible for your custom form/IFrame.<br /><br />You can do this by placing the following script in the OnLoad event of the CRM customized form:<pre>OnLoad()<br />{<br /> window.moveTo(0,0);<br /> window.resizeTo(screen.availWidth, screen.availHeight);<br />}</pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38895959-749312578819556051?l=www.simonrhart.com'/></div>Simon Harthttp://www.blogger.com/profile/08526568682625258690noreply@blogger.com0