Pages

Monday 7 May 2012

Interception and ServiceLocator in Unity

This time I would like to familiarize you with two interesting concepts of Unity (IoC Container) which you can find very useful.

Interceptors allow programmers to run some functionality before or after a selected piece of code. This approach is called Aspect-Oriented Programming (AOP) and its main goal is to increase modularity through separation of cross-cutting concerns e.g. logging messages before and after a code execution. The following example shows how easy you can apply logging in a method using a [MethodHandler()] attribute. 

ServiceLocator is an excellent concept of the Unity but I do not like the fact that it can be easily abused and overdosed. An example below shows two different approaches for creating an instance of a Logger class.  First one is using constructor injection and the second one is using ServiceLocator (have a look at the constructors). The only one case scenario when ServiceLocator seems to be very useful is a situation when we have a class created outside of the Unity and this class needs access to the other types registered in a container. An example below shows how to make ServiceLocator aware of the Unity.

   1:          class Program
   2:          {
   3:              static void Main(string[] args)
   4:              {
   5:                  IUnityContainer unity = new UnityContainer();
   6:                  UnityServiceLocator locator = new UnityServiceLocator(unity);
   7:                  ServiceLocator.SetLocatorProvider(() => locator);
   8:   
   9:                  unity.AddNewExtension<Interception>();
  10:                  unity.RegisterType<ILogger, Logger>();
  11:                  unity.RegisterType<ITest, Test>().Configure<Interception>().SetDefaultInterceptorFor<ITest>(new InterfaceInterceptor());
  12:   
  13:                  unity.Resolve<ITest>().Execute();
  14:                  Console.ReadKey();
  15:              }
  16:          }
  17:   
  18:          public class Test : ITest
  19:          {
  20:              public void Execute()
  21:              {
  22:                  Console.WriteLine("Execute Method Body");
  23:              }
  24:          }
  25:   
  26:          public interface ITest
  27:          {
  28:              [MethodHandler()]
  29:              void Execute();
  30:          }
  31:   
  32:          public class CallHandler : ICallHandler
  33:          {
  34:              private IUnityContainer _container;
  35:              private ILogger _logger;
  36:   
  37:              public CallHandler(IUnityContainer container, ILogger logger)
  38:              {
  39:                  _logger = logger;
  40:              }
  41:   
  42:              public CallHandler()
  43:              {
  44:                  _logger = ServiceLocator.Current.GetInstance<ILogger>();
  45:              }
  46:   
  47:              public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
  48:              {
  49:                  _logger.LogPreMessage(input.MethodBase.Name);
  50:                  IMethodReturn methodReturn = getNext()(input, getNext);
  51:                  _logger.LogPostMessage(input.MethodBase.Name);
  52:                  return methodReturn;
  53:              }
  54:   
  55:              public int Order
  56:              {
  57:                  get;
  58:                  set;
  59:              }
  60:          }
  61:   
  62:          public class MethodHandlerAttribute : HandlerAttribute
  63:          {
  64:              public MethodHandlerAttribute()
  65:              {
  66:              }
  67:   
  68:              public override ICallHandler CreateHandler(IUnityContainer container)
  69:              {
  70:                  return new CallHandler(container);
  71:              }
  72:          }
  73:   
  74:          interface ILogger
  75:          {
  76:              void LogPreMessage(string msg);
  77:              void LogPostMessage(string msg);
  78:          }
  79:   
  80:          class Logger : ILogger
  81:          {
  82:              public void LogPreMessage(string msg)
  83:              {
  84:                  Console.WriteLine("Pre -> " + msg);
  85:              }
  86:   
  87:              public void LogPostMessage(string msg)
  88:              {
  89:                  Console.WriteLine("Post -> " + msg);
  90:              }
  91:          }
  92:      }

Useful links:

Sunday 29 April 2012

Live Tiles

One of the most expected features of Mango release were live tiles allowing developers to present data on the Home screen. I was quite exited about this feature especially that I wanted to give users opportunity to learn new words or whole sentences. You can see it in action on Multi-Translator Webpage or you can install it from Marketplace.There are actually few ways to present data in live tiles.

FindAndDeleteTile method
   1:          private void FindAndDeleteTile(string tileName)
   2:          {
   3:              ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("DefaultTitle="+tileName));
   4:              if (tile != null)
   5:                  tile.Delete();
   6:          }

TileHelper class
   1:   public static class TileHelper
   2:      {
   3:          public static void CreateTile(string content, string fileName, string originalFileName)
   4:          {
   5:              TextBlock text = new TextBlock()
   6:              {
   7:                  Width = 173,
   8:                  Height = 173,
   9:                  TextWrapping = TextWrapping.Wrap,
  10:                  Foreground = new SolidColorBrush(Colors.White),
  11:                  Padding = new Thickness(5, 5, 5, 60),
  12:                  FontSize = 18,
  13:                  Clip = new RectangleGeometry { Rect = new Rect(0, 0, 173, 135) }
  14:              };
  15:              text.Text = content;
  16:              Canvas canvas = new Canvas() { Width = 173, Height = 173, Background = new SolidColorBrush(Colors.Blue) };
  17:              canvas.Children.Add(text);
  18:   
  19:              StreamResourceInfo sri = Application.GetResourceStream(new Uri(originalFileName, UriKind.Relative));
  20:              BitmapImage src = new BitmapImage();
  21:              src.SetSource(sri.Stream);
  22:              WriteableBitmap background = new WriteableBitmap(src);
  23:              WriteableBitmap bmp = new WriteableBitmap((int)canvas.Width, (int)canvas.Height);
  24:              bmp.Render(canvas, null);
  25:              bmp.Invalidate();
  26:   
  27:              for (int x = 0; x < canvas.Width; x++)
  28:                  for (int y = 0; y < canvas.Height; y++)
  29:                      //Detect the colour different from your canvas background (in this case Blue) 
  30:                      //and replace the background.jpg pixel with the one from your canvas    
  31:                      if (bmp.Pixels[y * (int)canvas.Width + x] != BitConverter.ToInt32(new byte[] { 255, 0, 0, 255 }, 0))
  32:                          background.Pixels[y * (int)canvas.Width + x] = bmp.Pixels[y * (int)canvas.Width + x];
  33:   
  34:              var iss = IsolatedStorageFile.GetUserStoreForApplication();
  35:              using (var stm = iss.CreateFile(fileName))
  36:                  background.SaveJpeg(stm, 173, 173, 0, 100);
  37:          }
  38:   
  39:          public static void CreateRenderedTile(FrameworkElement frameworkElement, string fileName)
  40:          {
  41:              WriteableBitmap bmp = new WriteableBitmap((int)frameworkElement.Width, (int)frameworkElement.Height);
  42:              bmp.Render(frameworkElement, null);
  43:              bmp.Invalidate();
  44:   
  45:              var iss = IsolatedStorageFile.GetUserStoreForApplication();
  46:              using (var stm = iss.CreateFile(fileName))
  47:                  bmp.SaveJpeg(stm, 173, 173, 0, 100);
  48:          }
  49:      }
  1. Default approach - using API
       1:          var filename = "/Shared/ShellContent/renderedF.jpg";
       2:          var filenameBack = "/Shared/ShellContent/renderedB.jpg";
       3:          TileHelper.CreateRenderedTile(frontBorder, filename);
       4:          TileHelper.CreateRenderedTile(backBorder, filenameBack);
       5:   
       6:          FindAndDeleteTile("Rendered");
       7:          StandardTileData NewTileData = new StandardTileData
       8:          {
       9:              BackgroundImage = new Uri("isostore:" + filename, UriKind.Absolute),
      10:              Title = "rendered - front",
      11:              BackTitle = "rendered - back",
      12:              BackBackgroundImage = new Uri("isostore:" + filenameBack, UriKind.Absolute)
      13:          };
      14:          ShellTile.Create(new Uri("/MainPage.xaml?DefaultTitle=Rendered", UriKind.Relative), NewTileData);
  2. Custom approaches:
    • Rendered - Saving the content of controls visible on the screen into a file and using it as a tile background
         1:          var filename = "/Shared/ShellContent/renderedF.jpg";
         2:          var filenameBack = "/Shared/ShellContent/renderedB.jpg";
         3:          TileHelper.CreateRenderedTile(frontBorder, filename);
         4:          TileHelper.CreateRenderedTile(backBorder, filenameBack);
         5:   
         6:          FindAndDeleteTile("Rendered");
         7:          StandardTileData NewTileData = new StandardTileData
         8:          {
         9:              BackgroundImage = new Uri("isostore:" + filename, UriKind.Absolute),
        10:              Title = "rendered - front",
        11:              BackTitle = "rendered - back",
        12:              BackBackgroundImage = new Uri("isostore:" + filenameBack, UriKind.Absolute)
        13:          };
        14:          ShellTile.Create(new Uri("/MainPage.xaml?DefaultTitle=Rendered", UriKind.Relative), NewTileData);
    • In memory - Saving a content of controls generated in memory into a file and using it as a tile background
         1:          var filename = "/Shared/ShellContent/inMemoryF.jpg";
         2:          var filenameBack = "/Shared/ShellContent/inMemoryB.jpg";
         3:          TileHelper.CreateTile(front.Text, filename, "Images/background.jpg");
         4:          TileHelper.CreateTile(back.Text, filenameBack, "Images/backgroundBack.jpg");
         5:   
         6:          FindAndDeleteTile("InMemory");
         7:          StandardTileData NewTileData = new StandardTileData
         8:          {
         9:              BackgroundImage = new Uri("isostore:" + filename, UriKind.Absolute),
        10:              Title = "in memory - front",
        11:              BackTitle = "in memory - back",
        12:              BackBackgroundImage = new Uri("isostore:" + filenameBack, UriKind.Absolute)
        13:          };
        14:          ShellTile.Create(new Uri("/MainPage.xaml?DefaultTitle=InMemory", UriKind.Relative), NewTileData);
Useful links:

Thursday 12 January 2012

What are the most profitable apps?

If you ask yourself what type of app you should create from the profitability point of view, just have a look below.