Welcome to EMC Consulting Blogs Sign in | Join | Help

Jon Sharratt's Blog

  • Microsoft Windows Phone 7 – MVVM Light NotifyPropertyChanged with Mono Cecil

    As you may or may not be aware I have recently spending some time trying to get a re-usable MVVM template together.  On my voyage of discovery when creating this I wanted to take out the standard boiler plate NotifyPropertyChanged code form the MVVM Light Toolkit.  I wanted to use AOP (Aspect Orientated Programming) so that on properties I could just have a single attribute [PropertyChanged] and then it would all be taken care of automagically.  Obviously the big advantage of this is that I could then use auto properties to provide a much cleaner code base within my ViewModels.

    Example of the end result:

    [PropertyChanged]
    public string RecordingMenuItemText { get; set; }

    So how do we go about this ? Enter the world of Mono Cecil and a custom build task to the rescue.  The process I followed was quite simple, build the application and then weave IL against any properties that have the [PropertyChanged] attribute via Mono Cecil.  After this was done I just needed to update the XAP file so that i gets deployed to the Emulator / Device.

     

    image

    Putting it all together…

    To code for the build task takes a single property so you can specify the assembly to weave the code into.  Below is the code I used to inject IL from the MVVM Light Toolkit.  I added a reference to the MVVM Light assembly so that I could weave the IL for notify property changed method within the ViewModelBase class adding in the string parameter for the property name from MVVM Light.

    namespace SugarTank.Build
    {
    using System;
    using System.Reflection;
    using GalaSoft.MvvmLight;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using Mono.Cecil;
    using Mono.Cecil.Cil;

    public class PropertyChangedTask : Task
    {
    /// <summary>
    /// When overridden in a derived class, executes the task.
    /// </summary>
    /// <returns>
    /// true if the task successfully executed; otherwise, false.
    /// </returns>
    public override bool Execute()
    {
    this.InjectMsil();

    return true;
    }

    /// <summary>
    /// Injects the MSIL.
    /// </summary>
    private void InjectMsil()
    {
    ModuleDefinition module = ModuleDefinition.ReadModule(this.AssemblyPath);

    foreach (TypeDefinition type in module.Types)
    {
    foreach (PropertyDefinition prop in type.Properties)
    {
    foreach (CustomAttribute attribute in prop.CustomAttributes)
    {
    if (attribute.Constructor.DeclaringType.FullName.Contains("PropertyChanged"))
    {
    ILProcessor msilWorker = prop.SetMethod.Body.GetILProcessor();

    Instruction ldarg0 = msilWorker.Create(OpCodes.Ldarg_0);

    var raisePropertyChangedInfo = typeof (ViewModelBase).GetMethod(
    "RaisePropertyChanged",
    BindingFlags.Public |
    BindingFlags.NonPublic |
    BindingFlags.Instance, null, new[] {typeof (string)}, null);

    var raisePropertyChanged = module.Import(raisePropertyChangedInfo);

    Instruction propertyName = msilWorker.Create(OpCodes.Ldstr, prop.Name);

    Instruction callRaisePropertyChanged = msilWorker.Create(OpCodes.Callvirt,
    raisePropertyChanged);

    msilWorker.InsertBefore(prop.SetMethod.Body.Instructions[0],
    msilWorker.Create(OpCodes.Nop));

    msilWorker.InsertBefore(
    prop.SetMethod.Body.Instructions[prop.SetMethod.Body.Instructions.Count - 1],
    ldarg0);

    msilWorker.InsertAfter(ldarg0, propertyName);

    msilWorker.InsertAfter(propertyName, callRaisePropertyChanged);

    msilWorker.InsertAfter(callRaisePropertyChanged, msilWorker.Create(OpCodes.Nop));
    }
    }

    module.Write(AssemblyPath);
    }
    }
    }

    /// <summary>
    /// Gets or sets the assembly path.
    /// </summary>
    /// <value>The assembly path.</value>
    [Required]
    public string AssemblyPath { get; set; }
    }
    }

    Now all we need to do is edit the Windows Phone 7 project file and hook into the after build event to execute our build task.  To do this I just edited the project file in notepad and added the following:

      <Import Project="$(SolutionDir)References\Community Tasks\MSBuild.Community.Tasks.Targets" />
      <UsingTask TaskName="SugarTank.Build.PropertyChangedTask" AssemblyFile="$(SolutionDir)References\Custom Build Tools\SugarTank.Build.dll"/>

      <Target Name="AfterBuild">
        <CallTarget RunEachTargetSeparately="True" Targets="CopyManifest;CopySplashScreen;WeaveCode;CreateZip" />
      </Target>
      <Target Name="CopyManifest">
        <Copy SourceFiles="$(ProjectDir)\Properties\WMAppManifest.xml" DestinationFolder="$(TargetDir)" />
      </Target>
      <Target Name="CopySplashScreen">
        <Copy SourceFiles="$(ProjectDir)\SplashScreenImage.jpg" DestinationFolder="$(TargetDir)" />
      </Target>
      <Target Name="WeaveCode">
        <PropertyChangedTask AssemblyPath="$(TargetPath)" />
      </Target>
      <Target Name="CreateZip">
        <ItemGroup>
          <ZipFiles Include="$(TargetDir)\*.*" Exclude="$(TargetDir)\*.xap;$(TargetDir)\*.pdb;$(TargetDir)\*.zip" />
        </ItemGroup>
        <Zip Files="@(ZipFiles)" WorkingDirectory="$(TargetDir)" ZipFileName="$(TargetDir)SugarTank.Mobile.xap" />
      </Target>

    You will notice I have a few other targets I run, these manually create the XAP file as I couldn’t find a way via MSBuild to open up the XAP file and replace the single assembly.  I was hoping after the IL was weaved in the XAP file would be created and the updated assembly would automatically make its way into the XAP.  

    But from what I can see it creates the XAP before the assembly has the code weaved into it which has forced me to take this approach and manually create a valid XAP.

    If you know of a better approach to amend the XAP file it would be greatly appreciated.
    @jsharratt

  • Windows Phone 7 MVVM Template Interim Release

    Just a quick post to inform people there is now a released a version of the source code / template in a handy zip file.  Hopefully will allow people to try out and this will provide an easy way to start developing Windows Phone 7 Silverlight applications.

    The release is hosted on CodePlex along with some documentation to you get up and running.

    Windows Phone 7 MVVM Template:
    http://bit.ly/dEW8lW

    Feedback is very welcome, any suggestions or new ideas that you would like implemented would be great.

    Enjoy!

  • Windows Phone 7 MVVM Silverlight Template - Update

    After my previous post seems to have gained some interest I decided to update it to add even more functionality.  But rather than just leaving everyone to there own devices I thought I would explain a few things within the template.  So lets begin….

    First of all I have now moved the project into CodePlex and can be located at http://wp7template.codeplex.com feel free to post problems or suggestions.

    Launcher Manager

    The launcher manager exposes all launchers that are available for Windows Phone 7.  If you are not aware of launchers MSDN has a great set of documentation on what is available (http://msdn.microsoft.com/en-us/library/ff769550%28v=VS.92%29.aspx).  To use the launchers all you need to do is add the dependency into your View Model and execute the relevant methods exposed to you.  Launchers are tasks that have no call backs after they are executed.

    Below is a simple example of a view model that has a command to launch a phone call task.

       1: public class LauncherChooserViewModel : ViewModelBase
       2: {
       3:     /// <summary>
       4:     /// The injected launcher manager.
       5:     /// </summary>
       6:     private readonly ILauncherManager launcherManager;
       7:  
       8:     /// <summary>
       9:     /// Initializes a new instance of the <see cref="LauncherChooserViewModel"/> class.
      10:     /// </summary>
      11:     /// <param name="launcherManager">The launcher manager.</param>
      12:     public LauncherChooserViewModel(
      13:         ILauncherManager launcherManager)
      14:     {
      15:         this.launcherManager = launcherManager;
      16:  
      17:         this.WireEvents();
      18:         this.WireCommands();
      19:     }
      20:  
      21:     /// <summary>
      22:     /// Wires the events.
      23:     /// </summary>
      24:     private void WireEvents()
      25:     {
      26:     }
      27:  
      28:     /// <summary>
      29:     /// Wires the commands.
      30:     /// </summary>
      31:     private void WireCommands()
      32:     {
      33:         this.MakePhoneCallCommand = new RelayCommand(MakePhoneCall);
      34:     }
      35:  
      36:     /// <summary>
      37:     /// Makes the phone call.
      38:     /// </summary>
      39:     private void MakePhoneCall()
      40:     {
      41:         this.launcherManager.MakeCall(new PhoneNumber("Jon Sharratt", "000000000000"));
      42:     }
      43:  
      44:     /// <summary>
      45:     /// Gets or sets the make phone call command.
      46:     /// </summary>
      47:     /// <value>The make phone call command.</value>
      48:     public ICommand MakePhoneCallCommand { get; private set; }
      49: }

    Chooser Manager

    The chooser manager has the same principles as the launcher manager but with a subtle difference that they can return a TaskResult.  For example you can execute the choose photo task and upon a user selecting an image this will be returned in the result for you to use.  Lets take this as an example and add it to our View Model.  You will notice we attach to the ChoosePhotoTaskCompleted event.  This will fire once a user has selected a photo returning the appropriate result.

       1: public class LauncherChooserViewModel : ViewModelBase
       2: {
       3:     /// <summary>
       4:     /// The injected launcher manager.
       5:     /// </summary>
       6:     private readonly ILauncherManager launcherManager;
       7:  
       8:     /// <summary>
       9:     /// The injected chooser manager.
      10:     /// </summary>
      11:     private readonly IChooserManager chooserManager;
      12:  
      13:     /// <summary>
      14:     /// Initializes a new instance of the <see cref="LauncherChooserViewModel"/> class.
      15:     /// </summary>
      16:     /// <param name="launcherManager">The launcher manager.</param>
      17:     /// <param name="chooserManager">The chooser manager.</param>
      18:     public LauncherChooserViewModel(
      19:         ILauncherManager launcherManager,
      20:         IChooserManager chooserManager)
      21:     {
      22:         this.launcherManager = launcherManager;
      23:         this.chooserManager = chooserManager;
      24:  
      25:         this.WireEvents();
      26:         this.WireCommands();
      27:     }
      28:  
      29:     /// <summary>
      30:     /// Wires the events.
      31:     /// </summary>
      32:     private void WireEvents()
      33:     {
      34:         this.chooserManager.ChoosePhotoTaskCompleted += ChoosePhotoTaskCompleted;
      35:     }
      36:  
      37:     /// <summary>
      38:     /// Chooses the photo task completed.
      39:     /// </summary>
      40:     /// <param name="sender">The sender.</param>
      41:     /// <param name="e">The <see cref="PhotoResult"/> instance containing the event data.</param>
      42:     private void ChoosePhotoTaskCompleted(object sender, EventArgs<PhotoResult> e)
      43:     {
      44:         if (e.Value.TaskResult == TaskResult.OK)
      45:         {
      46:             MessageBox.Show(e.Value.OriginalFileName);
      47:         }
      48:     }
      49:  
      50:     /// <summary>
      51:     /// Wires the commands.
      52:     /// </summary>
      53:     private void WireCommands()
      54:     {
      55:         this.MakePhoneCallCommand = new RelayCommand(MakePhoneCall);
      56:         this.SelectPhotoCommand = new RelayCommand(SelectPhoto);
      57:     }
      58:  
      59:     /// <summary>
      60:     /// Makes the phone call.
      61:     /// </summary>
      62:     private void MakePhoneCall()
      63:     {
      64:         this.launcherManager.MakeCall(new PhoneNumber("Jon Sharratt", "000000000000"));
      65:     }
      66:  
      67:     /// <summary>
      68:     /// Selects the photo.
      69:     /// </summary>
      70:     private void SelectPhoto()
      71:     {
      72:         this.chooserManager.ChoosePhoto();
      73:     }
      74:  
      75:     /// <summary>
      76:     /// Gets or sets the make phone call command.
      77:     /// </summary>
      78:     /// <value>The make phone call command.</value>
      79:     public ICommand MakePhoneCallCommand { get; private set; }
      80:  
      81:     /// <summary>
      82:     /// Gets or sets the select photo command.
      83:     /// </summary>
      84:     /// <value>The select photo command.</value>
      85:     public ICommand SelectPhotoCommand { get; private set; }
      86: }

    Theme Extension

    Just a small addition I have within the project is the ability within the view model logic to easily determine the current theme enabled on the phone.  To do this it is as simple as the following:

       1: if (Application.Current.Theme() == Theme.Dark)

    Pivot or Panorama

    The template itself is based on the default Visual Studio 2010 templates that comes out of the box with the Windows Phone 7 Developer Tools. The template also includes the default view for a Panorama application so you can easily get started whatever route you wish to take.

    Basically if you wish to get going on a Panorama style application all you require to do is open the WMAppManifest.xml file and amend the the navigation page from PivotMainPage.xaml to PanoramaMainPage.xml and then delete the PivotMainPage.xaml file located within the Views folder.

    That’s all for now folks…. next stop testing and globalization.

    Twitter: @jsharratt

  • Jump Start : Silverlight Windows Phone 7 Template

    I suddenly realised every time I started a new project for Windows Phone 7 Development for Silverlight I was repeating my initial setup of projects way to much.  Not only that it was hampering my creativity of “just getting on with coding, the fun part!” Since this eureka..ka.ka.ka.ka moment (should have come sooner) I decided to setup a clean implementation of the way I like to approach Silverlight / Windows Phone 7 development, based on my current knowledge. 

    After the “clean template” was setup I decided to use a great tool that was recently released at http://opensource.endjin.com/templify/.  Templify would allow me to package the clean template together and simply allow me in the future to just right click in Windows Explorer and deploy my template.  Simple, easy and a much more effective way of working.  I would recommend taking a look at http://blog.endjin.com/2010/10/introducing-templify/ to read more on this awesome little tool.

    The choices….

    Of course there are many approaches and many tools at a developers disposal to implement MVVM.  My main goal was to create a simple template that was lightweight and as clean as possible.  I chose NInject for Dependency Injection and the MVVM Light framework to take care of my view models, commands and so forth.

    Panorama or Pivot

    The template itself is based on the default Visual Studio 2010 templates that comes out of the box with the Windows Phone 7 Developer Tools.  Once this was done I took this forward to turn it into a lean and mean MVVM template to develop from in the future.  The template also includes the default view for a Panorama application so you can easily get started whatever route you wish to take.

    Basically if you wish to get going on a Panorama style application all you require to do is open the WMAppManifest.xml file and amend the the navigation page from PivotMainPage.xaml to PanoramaMainPage.xml then delete the PivotMainPage.xaml file located within the Views folder.

    image 

    Hopefully you may find this useful when starting to develop your own Windows Phone 7 Silverlight applications.  Next job is to get a testing framework into the project.  If you have any feedback, requirements or suggestions please do not hesitate to comment or drop me a tweet at @jsharratt

    Download

    Update please see this updated post: http://bit.ly/acvbNj 

    Useful References:

    NInject - http://ninject.org/
    MVVM Light - http://www.galasoft.ch/mvvm/getstarted/ 
    Templify - http://opensource.endjin.com/templify/

  • Webcast: XNA Game Development for Windows Phone 7

    As I carry on my way to learning the XNA framework to hopefully create some awesome games on the Windows Phone 7 devices I thought I would share a few resources that I find along the way.

    Turns out the AT&T developer program are generously hosting a few webcasts to help developers get underway.  The first webcast which I had missed can be found here.  It introduces you to the tools and resources that are available for Windows Mobile 7.  The next webcast is specifically looking at XNA game development on the Windows Phone 7 Devices.

    Details can be found below of the upcoming Webcast (Registration is required).


    Date:
    July 15, 2010

    Event Start Time:
    10:00 AM Pacific Daylight Time (17:00 GMT)

    Duration: 1 hour

    Please Note: Registrations must be submitted at least 1 HOUR prior to scheduled event start time in order to be considered for approval.

    Join The AT&T Developer Program for this free webcast to learn an overview of how to build games for Windows Phone 7 with Microsoft XNA Game Studio 4. Learn about the developer tools, the XNA Framework, and the resources available to build interactive, compelling, games with Windows Phone 7.

    Presenter:
    Rob Cameron
    Industry Architect, Microsoft

    Rob Cameron is an Industry Architect with the Communications Sector in Microsoft focused on Windows Phone 7, Silverlight, XNA, embedded and Mediaroom. Rob has worked with the product team since October to help customer and partner early adopters get ready for Windows Phone 7.
     
     
  • Bing Ice Cream Van

    So this morning via Twitter I noticed that Bing is doing a promotion using a touring Ice Cream Van around the United Kingdom.  As the sun is shining "I decided" to head out and grab a taste of the Bing ice cream at lunch.

    Took some quick pictures :o) - full size photos are available from my flickr set located here

    Bing Van 1 Bing Ice Cream Van 2Bing Ice Cream Van 3
     

     

     

     

     


    I can confirm the orange ice cream I picked (more of a frozen lolly) was very tasty indeed.... oh and provided an insightful fact on the lolly stick itself.

    "In 1962 Decca decided to turn down the Beatles."

  • XNA - Pocket Rocket Game

    Pocket Rocket

    With all the excitement of the new Windows 7 Mobile Phone being released I thought it was time to get my head into something new.  I have started to build a small game that I hope to release to the Microsoft Marketplace in time for the release of the new Windows Mobile 7 devices.

    This is my first attempt at building a game using the Microsoft XNA Framework.  So far so good, currently I have tackled basic collision detection via intersection of rectangles and added some simple physics.  You will notice if you reload the page there is a randomly generated "wind effect" to add some dynamic gravity direction to push the rocket left or right as you decend (is the game sounding familiar yet ;o) ).

    The next step to enhance this further is to add per pixel collsion detection.  To show the progress so far I have very quickly converted the game using SilverSprite.

    Although it appears to run a little buggy / un-smooth in comparison to the Windows version it gives you some idea of where the game is going.

    Controls:
    W = Thrust, D = Right, A = Left

    R = Reset Fuel *

    * for some reson in the silverlight version the top left fuel gauge doesn't animate from 100% downwards.

    You must click the Silverlight window in order to start controlling the rocket with the keyboard:

     

  • Blippr Series Part 2 - LINQ To Blippr

    Summary

    clip_image002[1]Upon deciding to start this series of blogs I decided that in order for me to consume the Blippr API I would attempt to “try” and make my life easy. I decided that the easiest way would be to start writing a LINQ to Blippr provider (first ever try) so that it was possible to easily consume the Blippr platform in any .NET application I wrote or for that matter anyone in the .net community. The project itself is hosted on CodePlex and can be found at LINQ to Blippr. The project implements the wonderful LINQ Extender container to make life easy when attempting to create your own LINQ providers.

    I also have to give a massive appreciation and shout out to Chris Heald at Blippr for amending the API for me as I have been developing the LINQ provider.

    Using LINQ to Blippr

    Download the latest alpha release from LINQ to Blippr on CodePlex. Just to note that the provider is still in development as we speak and there are many features in testing.  Operations that are available within the Alpha release should work correctly.

    clip_image004[1]Once downloaded add a reference to both the LINQ Extender and LinqToBlippr assembly.

    You will also need an API key for write operations which can be obtained by visiting and logging into the following page: http://www.blippr.com/api

    The Titles Query

    To search for titles that are available on Blippr you can now easily do this for example to search for all Matrix titles across all media types you can do the following (you will notice that you are not required to supply an API key to perform searching on titles):

       1: BlipprContext context = new BlipprContext();
       2: var result = context.Titles.Where(t => t.Name == "Matrix");
    Creating a New Title

    Creating a new title for Blippr is also now very easy. The simplistic process is to construct a new Title object add it to the Titles query and submit the changes for example (you will need to initialize the context with an API key):

       1: BlipprContext context = new BlipprContext(“YOUR-API-KEY”);
       2:  
       3: Title matrixRampage2 = new Title(MediaType.Games, "Matrix Rampage 2");
       4: context.Titles.Add(matrixRampage2);
       5: context.Titles.SubmitChanges();

    It can take a little while for the Blippr site cache to refresh so you probably will not see your title added immediately.

    Filtering

    The Blippr API covers the following Media Types which you can also add to your expression:

       1: MediaType.Apps
       2: MediaType.Books
       3: MediaType.Games
       4: MediaType.Movies
       5: MediaType.Music

    Using the previous example we can now get all matrix games by specifying a media type:

       1: BlipprContext context = new BlipprContext();
       2: var result = context.Titles.Where(t => t.Name == "Matrix" 
       3:                                   && t.MediaType == MediaType.Games);

    You can also add to your expression a filter on score and the total amount of blips posted against the titles. As a quick reference I have provided some examples below:

    Score

    An expression that returns all “matrix” titles of any media type that has a score less than or equal to 70.

       1: BlipprContext context = new BlipprContext();
       2:  
       3: var result = context.Titles.Where(t => t.Name == "Matrix" &&
       4:                                   t.Score <= 70);
    Total Blips

    An expression that returns all “matrix” titles of any media type that has a total number of blips greater than 10.

       1: BlipprContext context = new BlipprContext();
       2:  
       3: var result = context.Titles.Where(t => t.Name == "Matrix" &&
       4:                                   t.TotalBlips > 10);
    Ordering

    Ordering by a specific property such as title is as simple as:

       1: BlipprContext context = new BlipprContext();
       2:  
       3: var result = context.Titles.Where(t => t.Name == "Matrix" &&
       4:                                   t.TotalBlips > 10)
       5:                                   .OrderByDescending(t => t.Name);

    If the Blippr API has a supporting order by clause then this will be done when requesting the xml data. If supporting functionality does not exist then ordering will be done in memory.

    Other Features....

    • Comments Query (BlipprContext.Comments)
      Add comments against blips.
      Get comments by blip id.

    • Blips Query (BlipprContext.Blips)
      Add new blip against a title.
      Get blips currently posted against a title.
      Delete a blip that you own.

    As the core element of Blippr is to “Blip” against titles you can follow the same syntax style to post a Blip against a title once you have searched and got your title id (Red Alert 3 is 345210):

       1: BlipprContext context = new BlipprContext(APIKEY);
       2: Blip redAlert3Blip = new Blip(345210, Rating.LoveIt, "Play this game every Wednesday with work mates. Great game!");
       3:  
       4: context.Blips.Add(redAlert3Blip);
       5: context.Blips.SubmitChanges();

    Under The Hood

    As previously mentioned the LINQ to Blippr library uses LINQ Extender. LINQ Extender provides a very easy to use framework for creating your own LINQ providers.

    In order to start creating LINQ to Blippr we first need to create a context class and then a LINQ Extender query; we will focus on the TitlesQuery only. Going forward any additional queries will follow a similar pattern.

    Lets Begin…

    As previously stated to begin we require a context class in order to initialize and access the relevant queries to return the data we require. For the LINQ to Blippr context there are a couple of constructors one that allows the API key to be passed through for operations that require authentication and one without.

    Lastly we have a property that returns a TitlesQuery which will allow us to execute expressions aginst the query to return the data we want.

       1: namespace Linq.Blippr
       2: {
       3:     using Factories;
       4:     using Queries;
       5:  
       6:     /// <summary>
       7:     /// Defines the Blippr context.
       8:     /// </summary>
       9:     public class BlipprContext
      10:     {
      11:         /// <summary>
      12:         /// The factory to return queries.
      13:         /// </summary>
      14:         private readonly QueryFactory queryFactory;
      15:  
      16:         /// <summary>
      17:         /// The api key.
      18:         /// </summary>
      19:         private readonly string apiKey;
      20:  
      21:         /// <summary>
      22:         /// The global titles query.
      23:         /// </summary>
      24:         private TitlesQuery titlesQuery;
      25:         
      26:         /// <summary>
      27:         /// Initializes a new instance of the <see cref="BlipprContext"/> class.
      28:         /// </summary>
      29:         /// <param name="apiKey">The API key.</param>
      30:         public BlipprContext(string apiKey)
      31:         {
      32:             this.apiKey = apiKey;
      33:             this.queryFactory = new QueryFactory();
      34:         }
      35:  
      36:         /// <summary>
      37:         /// Initializes a new instance of the <see cref="BlipprContext"/> class.
      38:         /// </summary>
      39:         public BlipprContext()
      40:         {
      41:             this.queryFactory = new QueryFactory();
      42:         }
      43:         /// <summary>
      44:         /// Gets the global titles query.
      45:         /// </summary>
      46:         public TitlesQuery Titles
      47:         {
      48:             get
      49:             {
      50:                 if (this.titlesQuery == null)
      51:                 {
      52:                     this.titlesQuery = this.queryFactory.CreateTitlesQuery(this.apiKey);
      53:                 }
      54:  
      55:                 return this.titlesQuery;
      56:             }
      57:         }
      58: }
    Titles Query

    We now have our Blippr context class it is now time to create our TitlesQuery that the property exposes. Firstly to create this we need to inherit from the Generic Query<T> class provided to us from the LINQ Extender assembly. We need to pass in the type of object that will be returned for the final result set.

       1: public class TitlesQuery : Query<Title>

    As the Blippr platform API can return either JSON, XML or YAML I decided to head down the de-serialization route and request Xml for results. The Title class is a plain object decorated with the .NET frameworks serialization Xml Attributes so that later on when we get the data and de-serialize it those properties will be populated. Clean, simple and readable. Below shows the Title object:

       1: namespace Linq.Blippr.CommonTypes
       2: {
       3:     using System;
       4:     using System.Xml.Schema;
       5:     using System.Xml.Serialization;
       6:     using Enums;
       7:     using LinqExtender.Attributes;
       8:  
       9:     /// <summary>
      10:     /// Determines a blippr title object.
      11:     /// </summary>
      12:     [Serializable]
      13:     [XmlRootAttribute(ElementName = "title", Namespace = "", IsNullable = false)]
      14:     public class Title
      15:     {
      16:         /// <summary>
      17:         /// Initializes a new instance of the <see cref="Title"/> class.
      18:         /// </summary>
      19:         public Title()
      20:         {
      21:         }
      22:  
      23:         /// <summary>
      24:         /// Initializes a new instance of the <see cref="Title"/> class.
      25:         /// </summary>
      26:         /// <param name="mediaType">Type of the media.</param>
      27:         /// <param name="name">The name of the title.</param>
      28:         public Title(MediaType mediaType, string name)
      29:         {
      30:             if (mediaType == MediaType.Titles)
      31:             {
      32: throw new Exception("Invalid media type please only use apps, books, games, movies or music.");
      33:             }
      34:  
      35:             this.MediaType = mediaType;
      36:             this.Name = name;
      37:         }
      38:  
      39:         /// <summary>
      40:         /// Gets or sets the unique id.
      41:         /// </summary>
      42:         [XmlAttribute(AttributeName = "id", Form = XmlSchemaForm.Unqualified)]
      43:         [UniqueIdentifier]
      44:         public long Id { get; set; }
      45:  
      46:         /// <summary>
      47:         /// Gets or sets the url link.
      48:         /// </summary>
      49:         [XmlAttribute(AttributeName = "link", Form = XmlSchemaForm.Unqualified)]
      50:         public string Link { get; set; }
      51:  
      52:         /// <summary>
      53:         /// Gets or sets the name.
      54:         /// </summary>
      55:         [XmlAttribute(AttributeName = "name", Form = XmlSchemaForm.Unqualified)]
      56:         public string Name { get; set; }
      57:  
      58:         /// <summary>
      59:         /// Gets or sets the total amount of reviews.
      60:         /// </summary>
      61:         [XmlAttribute(AttributeName = "reviews_count", Form = XmlSchemaForm.Unqualified)]
      62:         public long TotalBlips { get; set; }
      63:  
      64:         /// <summary>
      65:         /// Gets or sets the score rating.
      66:         /// </summary>
      67:         [XmlAttribute(AttributeName = "score", Form = XmlSchemaForm.Unqualified)]
      68:         public float Score { get; set; }
      69:  
      70:         /// <summary>
      71:         /// Gets or sets the images.
      72:         /// </summary>
      73:         [XmlElement(ElementName = "images", Form = XmlSchemaForm.Unqualified)]
      74:         public Images Images { get; set; }
      75:  
      76:         /// <summary>
      77:         /// Gets or sets a value indicating whether [media type].
      78:         /// </summary>
      79:         /// <value><c>true</c> if [media type]; otherwise, <c>false</c>.</value>
      80:         [XmlAttribute(AttributeName = "media_type", Form = XmlSchemaForm.Unqualified)]
      81:         public MediaType MediaType { get; set; }
      82:     }
      83: }

    Now on to the fun part where we can now override relevant methods in out Titles query to return the data. The following methods are overridden within the TitlesQuery class:

       1: protected override void SelectItem(IBucket bucket, IModify<Title> items)

    Processes a complex expression and adds results to the items IModify<Title> result set.

       1: protected override bool AddItem(IBucket bucket)

    Adds an item when submitting changes to the query.

       1: protected override Title GetItem(IBucket bucket)

    Retrieves a single item by its unique identifier.

    You will notice that commonly the IBucket is provided to each method signature. IBucket exposes information for the actual expression being executed. This allows us to handle and build up the request URL to send to the Blippr API. It contains all items by field name and the values for the expression along with the relation type (being Greater Than, Equal, Less Than…) and other information you can use.

    In LINQ to Blippr currently the logic has been separated out into individual repository classes. Let’s take AddItem(IBucket bucket) as an example as this is a simple operation to review:

       1: /// <summary>
       2: /// Adds a new the item.
       3: /// </summary>
       4: /// <param name="bucket">The bucket.</param>
       5: /// <returns><c>true</c> if addition was a success.</returns>
       6: protected override bool AddItem(IBucket bucket)
       7: {
       8:     if (string.IsNullOrEmpty(this.apiKey))
       9:     {
      10:         throw new NullReferenceException("Authentication is required, initialize the Blippr Context with your API key.");
      11:     }
      12:     
      13:     return this.titleRepository.Add(bucket);
      14: }
      15:  

    Then in our TitleRepository we can do the necessary implementation to add a new item via the Blippr API:

       1: /// <summary>
       2: /// Adds a title to blippr.
       3: /// </summary>
       4: /// <param name="bucket">The linq bucket.</param>
       5: /// <returns><c>true</c> if post was a success.</returns>
       6: public bool Add(IBucket bucket)
       7: {
       8:             if (bucket.Items[TitleFields.MediaType].Value != null)
       9:             {
      10:                 this.mediaType = (MediaType)bucket.Items[TitleFields.MediaType].Value;
      11:             }
      12:  
      13:             string query = string.Format(
      14:             UrlTemplates.POSTNewTitle,
      15:             this.mediaType.ToString().ToLowerInvariant(),
      16:             OutputFormat.Xml.ToString().ToLowerInvariant(),
      17:             bucket.Items[TitleFields.Name].Value,
      18:             this.ApiKey);
      19:  
      20:             bool result = this.PostData(query);
      21:  
      22:             return result;
      23: }

    The above grabs the expression information from the bucket builds up the URL in the correct format to post to Blippr and then returns a true or false value if the request was successful. Let’s break down an example:

    Say our code is the following:

       1: BlipprContext context = new BlipprContext(“YOUR-API-KEY”);
       2:  
       3: Title matrixRampage2 = new Title(MediaType.Games, "Matrix Rampage 2");
       4: context.Titles.Add(matrixRampage2);
       5: context.Titles.SubmitChanges();

    The IBucket items will store the values for each field by keys meaning:

    bucket.Items[“Title”] would represent matrixRampage2.Title value.
    bucket.Items[“MediaType”] would represent matrixRampage2.MediaType value.

    You can then take this further when building up expressions that select items with a Where clause. For example when we wish to query a title against the total number of blips we have the following code executed within the SelectItem function:

       1: BucketItem totalBlipsBucketItem = bucket.Items[TitleFields.TotalBlips];
       2:  
       3: if (totalBlipsBucketItem.Value != null)
       4: {
       5:     int totalBlips;
       6:  
       7:     if (!int.TryParse(totalBlipsBucketItem.Value.ToString(), out totalBlips))
       8:     {
       9:         throw new InvalidCastException("Total blips must not be of type " + totalBlipsBucketItem.PropertyType.Name);
      10:     }
      11:         
      12:     switch (totalBlipsBucketItem.RelationType)
      13:     {
      14:         case RelationType.GreaterThan:
      15:             query.Append("&min_reviews=" + (totalBlips + 1));
      16:             break;
      17:         case RelationType.GreaterThanEqual:
      18:             query.Append("&min_reviews=" + totalBlips);
      19:             break;
      20:         case RelationType.LessThan:
      21:             query.Append("&max_reviews=" + (totalBlips - 1));
      22:             break;
      23:         case RelationType.LessThanEqual:
      24:             query.Append("&max_reviews=" + totalBlips);
      25:             break;
      26:         default:
      27:             query.Append("&min_reviews=" + totalBlips + "&max_reviews=" + totalBlips);
      28:             break;
      29:     }
      30: }

    You will notice we use totalBlipsBucketItem.RelationType to determine how to handle each of the different relation types. For example below you will find that the above code deals with the t.TotalBlips > 1 part of expression below:

       1: var titles = context.Titles.Where(t => t.Name == "Iron Man" &&
       2:                                        t.MediaType == MediaType.Movies &&
       3:                                        t.TotalBlips > 1);

     Feedback and Comments

    Hopefully this gives you a good idea on how you can go about starting to create your own LINQ provider with LINQ Extender. I will announce the stable releases for LINQ to Blippr via Twitter, CodePlex and this blog… so stay tuned.

    If you have any creative ideas or begin to start using LINQ to Blippr in you applications I would love to hear about it. Alternatively there is twitter trend you can use #LinqToBlippr.

    I welcome any comments either about the blog content itself or suggestions in steering what you would like covered in the coming posts. You can leave a comment on my blog, drop me a mail or tweet me @jsharratt. 

    Lastly if you want to contribute to this project please free to get in touch.

    Blippr Blog Series
    • Blippr Series Part 1 - Introduction
    • Blippr Series Part 2 - Linq To Blippr
    • Blippr Series Part 3 - Windows 7 Mobile Blippr Application
    • Blippr Series Part 4 - Titanium Mobile Blippr Application
  • Blippr Series Part 1 - Introduction

    Introduction

    You never have to look to far these days when it comes to social media; it is not a new concept having been around for a while now. The explosion of social networking sites and application usage in recent years has been truly amazing. You will no doubt experience or touch social media in your day to day life whether you like it or not.

    Having worked on a few projects in the retail sector I always find it very exciting to see how far organizations are pushing the experiences for users. Concepts such as cross sells, 360 degree product views, extremely high definition images and swatch colour / texture options. Bringing it back to the social media aspect we see many sites today allowing customers to review products giving feedback and ratings. To quote Albert Einstein “The only source of knowledge is experience”; I know before I spend my hard pennies I would rather get the experience and confidence from others before the hassle of hitting the returns department.

    This brings me to a concept I came across when browsing for a social media application that combined the popularity of micro blogging and customer reviews. I found a concept more commonly known as “micro-reviewing”. Even more excitingly I found a community that integrates with your existing social accounts and is already gaining popularity.

    Blippr

    Blippr is a micro review site allowing users in a twitteresque manner submit reviews against products (currently covers music, books, games and applications). A user has an another feature in the form of a rating that goes along side the micro-review specifying whether you “Love”, “Like”, “Hate” or “Dislike” the product in question. Additional to this the site will recommend certain products based on your previous ratings that you may be interested in.

    Blog Series Preview

    In this blog series we will cover firstly how you we can harness Blippr easily into your Microsoft .NET applications with a newly created LINQ provider (Linq To Blippr). Secondly in this series I will touch on developing a Blippr mobile application for the recently announced Windows 7 Mobile Phone platform. We will then round off the series with developing a Blippr mobile application on both the Android and iPhone platforms using the amazing Titanium software.

    To you give you a taste of what we are hoping to achieve at the end of this blog series below are some draft prototypes for the windows mobile application. All code will be open source and freely available to download.

    clip_image002[7] clip_image004[7] clip_image006[7]

    Feedback and Comments

    I welcome any comments either about the blog content itself or suggestions in steering what you would like covered in the coming posts. You can leave a comment on my blog, drop me a mail or tweet me @jsharratt.

    Blippr Blog Series
    • Blippr Series Part 1 - Introduction
    • Blippr Series Part 2 - Linq To Blippr
    • Blippr Series Part 3 - Windows 7 Mobile Blippr Application
    • Blippr Series Part 4 - Titanium Mobile Blippr Application

This Blog

Syndication

News

Powered by Community Server (Personal Edition), by Telligent Systems