Informant Architecture

With the release of Informant v0.1.5.0 today I wanted to take a minute and talk about some of the changes and challenges I faced with this iteration. Let me first tell you what my goal was with this iteration. I wanted to create a single code base that could be reused in the Windows Service world as well as in WPF4, Silverlight 4, and Windows Phone 7. The challenge was finding which kind of class library can be shared with other kinds of applications. I discovered that Silverlight 3 was the appropriate base library type to use. Any .NET solution can reference SL3 libraries. I hoped to be able to make all of my model objects in SL3 assemblies and share them across all applications. However, I ran into some show stoppers in namespace conflicts. The model objects would be used in WCF therefore they needed to have DataContract and DataMemeber attributes applied to them. The namespace System.Runtime.Serialization cannot be shared between SL3 and WPF4. I got the following exception when I tried this: “Could not load file or assembly ‘System.Runtime.Serialization, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e’ or one of its dependencies. The system cannot find the file specified.” WPF4 does not understand and is not compatible with this version of the SL3 framework. Super big bummer! This meant that I could only use Interfaces to enforce my model object APIs. Since I wanted consistency this is exactly what I did. Only one SL3 library is shared between all of the UI applications and the Windows Service.

The next hurdle was handling a WCF service reference that would work in all scenarios. I found that this was also not possible, or rather was not ideal for my situation. I wanted my WPF4 application to be very rich and have have duplex channels which are not supported in SL3/4 or Wp7. This meant that every framework had to have it’s own non-reusable reference to the service. These references live in the DataProviders.[Framework] assemblies. Even though I know that the model objects coming from the service are implementing the Interfaces defined in the shared library, I cannot treat these objects as those Interfaces when they come out of the service. I must be able to do this in order for my UI, ViewModels, and other DataProvider dependent assemblies to be shared across frameworks. To overcome this I made a partial class for each model object coming from the service and had the partial I made implement the correct Interface. This caused two problems for me. First, the Interfaces were using IEnumerable<T> which is not supported in WCF. The models from WCF all use List<T> when they come across the wire. In order to solve this I had to tell WCF to change the names of the IEnumerable<T> properties when they were sent across the wire and I had to make each IEnumerable<T> property in the partial I made use the List<T> property from the WCF partial class as the backing field. This was preferred over changing the Interfaces to enforce desired behavior. Second, there was an error that said the WCF partial and the partial I made had difference base classes after I implemented the Interface. This was so very confusing, and it took me a while to figure out. Turns out Visual Studio 2010 (and perhaps prior versions) specify each model as inheriting from object.

public partial class Contact: object

This behavior is unnecessary and redundant since every object in C# already inherits from object by default. I had to go through the Auto Generated code and remove all explicit inheritance from object. After I did this the application compiled just fine. Strangely enough, now whenever I update my service reference the explicit inheritance is added back in, but does not cause an error as it did the first time. While I’d love to understand what exactly was going on with the error, it seems to have resolved and is no longer causing me issues so I’ve stopped looking into it.

The UI presented the final difficulty. We use DelegateCommands all over in our ViewModels here at InterKnowlogy and I wanted to do the same in my VMs. The problem is the underlying implementation of the DelegateCommand class, and other classes, are so different that a VM specifically designed for each framework must exist. Much of the core functionality of each VM can be shared in a base VM but each framework must still have a specific VM implementation. The idea that VMs can be reused without modification is false, but a good deal of each VM can be shared, and that’s exactly what I took advantage of.

With all of that said and done I now have a working version of Informant for WPF4 referencing a Windows Service that is installed on the same machine. The service is required so users can close the application and leave their computer on and Informant will still send all of the desired SMS messages. The Wp7.5 (Mango) version is next on my plate. This version will require me to refactor the Windows Service to support a RESTful API. The service will also need to be hosted on a publicly accessible server. My goal is to enable Wp7 users to be able to send SMS messages to their contacts and contact groups. A SL5 version will then be next available on the same server as the RESTful service.

The ability to reference SL3 libraries in the different .NET frameworks has greatly decreased the amount of work required to develop a framework specific application that fulfills the same purpose. It’s quite amazing and awesome. However, a small word of caution should be made known. The new Windows 8 WinRT framework is NOT compatible with this pattern. Each library must be a WinRT library compiled against WinRT. So I will not be able to reuse the libraries, as is, in Windows 8 WinRT. This is a huge bummer, but makes sense as I’ve learned more about what WinRT really is.

Kinect in Windows 8 on .NET Rocks

My coworker Danny Warren and I recorded a .NET Rocks session a couple weeks that just went live tonight.  We discuss how we got a Windows 8 / WinRT application to communicate with the Microsoft Kinect.  I blogged about how we pulled that off here, but check out the podcast to hear it first hand.

.NET Rocks show #714 – Dan Hanan and Danny Warren Mix Kinect and Metro

Windows 8 Development–First Impressions

Along with 5000 other developers, I attended //BUILD/ in September and came home with the Samsung pre-release hardware loaded with Visual Studio 11 and the Win8 bits.  Since then, I’ve been writing a few apps, getting my feet wet writing code for Metro / WinRT apps in C#.  Here are some early impressions on the Windows 8 operating system in general, and then some thoughts on what it takes to develop Metro apps.

Don’t Make Me Hop That Fence Again

The grand new look of Windows 8 is the “Metro” style interface that you see right away on the Start Screen.  The traditional start menu is gone, you don’t have a hierarchy of StartScreenstart menu icons that you wade through, and you don’t have a bunch of icons scattered on your desktop.  Instead you have the clean looking, larger sized “tiles”, some of which are “live”, showing you changes to application data in real-time.    You can find lots of info on the Win8 Metro interface here, so I won’t talk about that.  Apps written for Metro, built against the Windows Runtime (WinRT) run over here on this “Metro” side of the fence.

What is so interesting to me though is that there exists an alternate world in Windows 8 – the classic desktop.  This is where legacy apps run, where the familiar desktop can be littered with icons, the taskbar shows you what’s running,etc. Everything from old C and C++ code to .NET 4 apps run over here on this “Desktop” side of the fence.

DesktopSideSo here then is the problem. Throughout the day, I run a few apps to check Facebook and Twitter (Metro), then I startup Visual Studio 11 (desktop), then I start Task Manager (Metro), then maybe a command prompt (desktop).  Each time I’m in one environment and run an app that runs in the other, the OS switches context to the other side of the fence.  This becomes SUPER ANNOYING over the course of a day.  I’m in the desktop, all I want to do is fire up a command prompt.  Click the start menu (which takes me to the Metro start screen), then choose command prompt, which switches me back to where I just came from and fires up the command prompt.  I’ve become accustomed to pinning all my necessary apps to the desktop side taskbar so I don’t have to go to the Metro screen to run time.

Enough of the Rant – What About Development?

The Windows 8 Runtime (WinRT) is a completely re-written layer akin to the old Win32 API that provides lots of new services to the application developer.  When sitting down to write a new app, you have to decide right away, are you writing a .NET 4.5 app, or are you writing a Metro app.  (This dictates which side of the fence you’ll be hanging out in.)  Some of the coolest features of the Win8 runtime are:

Contracts

Contracts are a set of capabilities that you declare your application to have, and the OS will communicate with your app at runtime based on the contracts.  Technically they’re like interfaces, where you SearchResultspromise to implement a set of functionality so the OS can call you when it needs to.  The most popular contracts are those that are supported by the “Charms” – Search, Share, and Settings.  These are super cool.  Implement a couple methods and your app participates as a search target, so the when the user enters some text in the search charm, your app is listed and you furnish the results.

 

 

protected override void OnLaunched( LaunchActivatedEventArgs args )
{
    var pane = Windows.ApplicationModel.Search.SearchPane.GetForCurrentView();
    pane.QuerySubmitted += QuerySubmittedHandler;

    pane.SuggestionsRequested += SuggestionsRequestedHandler;
    pane.ResultSuggestionChosen += ResultSuggestionChosenHandler;

    pane.PlaceholderText = "Search for something";

	// ...
}

private void QuerySubmittedHandler( SearchPane sender, SearchPaneQuerySubmittedEventArgs args )
{
    var searchResultsPage = new SearchTest.SearchResultsPage1();
    searchResultsPage.Activate( args.QueryText );
}

private void SuggestionsRequestedHandler( SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args )
{
    var searchTerm = args.QueryText;

    var sugg = args.Request.SearchSuggestionCollection;
    for ( int i = 0; i < 5; i++ )
    {
        // just faking some results
        // here you would query your DB or service
        sugg.AppendResultSuggestion( 
            searchTerm + i, 
            "optional description " + i, 
            i.ToString(), 
            Windows.Storage.Streams.StreamReference
              .CreateFromUri( new Uri( "someurl.jpg" ) ),
            "alternate text " + i );
    }

    //defer.Complete();
}

protected override void OnSearchActivated( SearchActivatedEventArgs args )
{
    var searchResultsPage = new SearchTest.SearchResultsPage1();
    searchResultsPage.Activate( args.QueryText );
}

ShareSharing is just about as easy. Declare the contract in your manifest and your app is a share target.  When the user chooses to share to your app, the OS sends you the data the user is sharing and you party on it.

protected override void OnSharingTargetActivated( ShareTargetActivatedEventArgs args )
{
	var shareTargetPage = new ShareTestTarget.SharingPage1();
	shareTargetPage.Activate( args );
}

Settings leave a little bit to be desired in my opinion. You declare the contract, and add a “command” to tell the OS to put in the settings charm panel.  But when the user chooses that command (button), your app has to show its own settings content (usually in a slide out panel from the right).  This is a 4 step process to make any settings changes in your app (swipe from right, touch the button, change settings, dismiss the panel). I really hope in future versions they figure out a way to embed our application settings content right there in the settings panel, not in our own app.

    Windows.UI.ViewManagement.ApplicationLayout.GetForCurrentView().LayoutChanged += LayoutChangedHandler;
    DisplayProperties.OrientationChanged += OrientationChangedHandler;
    Application.Current.Exiting += ExitingHandler;

    SettingsPane pane = SettingsPane.GetForCurrentView();
    SettingsCommand cmd = new SettingsCommand("1", "Pit Boss Settings", (a) =>
        {
            ShowSettingsPanel();
        });
    pane.ApplicationCommands.Add(cmd);

Async Everywhere

The WinRT team has built the APIs with asynchrony in mind from day one. At //BUILD/, we heard over and over that your UI should NEVER freeze because it’s busy doing something in the background.  To that end, any API that could potentially take longer than 50 milliseconds is implemented as an asynchronous method.  Using the async and await keywords (we’ve seen these in a CTP for .NET 4) that are built into the WinRT-based languages, we can write our code in a flowing, linear fashion that makes sense semantically.  No longer do we have to use BackgroundWorkers and worry about marshalling results back to the calling thread.

    HttpClient http = new HttpClient();
    var task = await http.GetAsync( url );

    string responseText = task.Content.ReadAsString();

“Free” Animations

XAML support is implemented in WinRT as native code, and is available to use from C#, VB, and C++.  One of the coolest features they added to what we’re already used to in WPF & Silverlight is the “built-in” animation library.  Simply add any number of transitions on a container element, and any of the associated operations in ANY OF ITS CHILDREN will use that transition.  The list of built-in transitions include: Entrance (content appearing for the first time), Content (change content from old to new), Reposition (fluidly move elements when they get repositioned), Add/Delete (fade out/in and move existing items), and Reorder.

  <Grid>
    <Grid.ChildTransitions>
      <TransitionCollection>
        <EntranceThemeTransition
            HorizontalOffset="500" />
      </TransitionCollection>
    </Grid.ChildTransitions>
  </Grid>

Well, I’ve jumped all around in this post, and it’s long enough already.  Look for future posts with more specifics about features and code that we’re working into our apps.

Some Development Gotchas (aka Bugs)

Here’s a quick list of some issues we’ve run into these first few weeks.

  • You can only set DataContext in code-behind – future releases will allow setting in XAML
  • There are a handful of bugs in FlipView.SelectedItem.  If you’re binding to the SelectedItem property, you have to manually set the SelectedItem to null and then back to the correct property (get it from your ViewModel) in code-behind.  This will obviously be fixed in a future release.
  • You must use ObservableVector<object> based properties in your VMs if you are binding to ItemsControls.ItemsSource and want the UI to update when there are changes to the collection.  ObservableVector<T> does not exist in the class library – you can find source code for it in many of the SDK samples.
  • Use the correct INotifyPropertyChanged implementation (from Windows.UI.Xaml.Data, not System.ComponentModel)
  • There is no VS item template for custom controls in C#, so VS won’t make you the Themes\Generic.xaml structure.  We’re still tracking this one down. We’ve used a Style resource to describe the template for a Button-derived custom control and it works, but you don’t get access to the Template property in OnApplyTemplate, so we’ve resorted to using VisualStateManager instead of referring to template parts and changing UI that way.
  • I’m sure there are more to come … in fact, check out my co-worker Danny’s post (should be up in the next couple days) with more details on what we’ve been encountering while writing our first few Win8 apps.

Check out the Win8 Metro developer forums for ongoing discussions of many other issues.