Tuesday, May 27, 2014

Decompiling BAML

We know that XAML is a declarative markup language. XAML simplifies creating a UI for .NET application created using WPF or Silverlight. It is simple and easy to create UI elements using XAML, and then separate the design from run-time logic by using code-behind files, joined to the markup by partial class definitions. So what is a BAML ?

BAML is the short form of Binary Application Markup Language, as the name implies it is a binary representation of the XAML file containing implementation details. It is nothing but  parsed, tokenism and XAML that is converted into binary format. Tokenized  means lengthier bits of XAML are replaced with shorter tokens. It is compressed declarative format that is faster to load and parse also it is smaller in size as compared to regular XAML.

So when you compile a WPF project, all XAML files whose build action are set to Page or Resource gets converted to BAML and then embedded as resource in the assembly. So now you have a binary object that is smaller and also optimized in a way that makes it faster to parse at runtime. BAML gets embedded as a resource so developer don't need to worry about linking,parsing or referencing anything  except calling InitializeComponent() in code-behind.

BAML is converted to implementation code during runtime, internally it is used for creating objects. If  you set the x:shared attribute to false, a new copy is created from the BAML every time you use the object. In earlier versions developers didn't have access to BAML, After WPF 4 the new implementation of XamlReader.Load(), BAML loading, Control & DataTemplates functionality with a new engine built on top of the new System.Xaml.dll, I know back in the early days of WPF that CAML was generated rather than BAML, looks like the WPF team has decided to eliminate it, and keep the BAML version.

Baml2006Reader :
Again as most of us know that in WPF, UI can be created either by code or by XAML-which is basically an declarative XML to describe object graphs. This approach makes UI development  easy and fast but parsing XAML file at runtime is quite expensive. So the MarkupCompiler converts the XAML file to BAML.The BAML API is something unique of WPF and was not public until .NET 4.0. Now it's available through the Baml2006Reader implementation. The following code shows how to load a BAML stream .Baml2006Reader uses Reflection to load the assemblies needed for decompilation, which is a little expensive.
var reader = new Baml2006Reader(stream);
var writer = new XamlObjectWriter(reader.SchemaContext);
while(reader.Read())
{
    writer.WriteNode(reader);
}
return writer.Result;
A simple way to decompile the generated BAML is by using the dotPeek from JetBrains or .NET Reflector. Lets walk through the process of installing the plugin.

dotPeek : We have to build and install a plugin for dotPeek. To install the plugin follow this steps.
  1. Download the addin Baml4dotPeek  from the github project https://github.com/cprieto/Baml4dotPeek
  2. Build the project, you might have to update reference to point to your dotPeek bin folder.
  3. A successful  build will generate a output file "BamlFromResource.dll".
  4. Copy this file to the dotpeek bin directory.
  5. Restart dotPeek, and verify form the Tools|Options, if you have the BamlDecompiler.



Once you have the plugin installed open any WFP project and expand the directory tree to find the resources . From the resources you will find some baml file, select any file and the window on the right will display the xaml for that resource.




Note: For Silverlight the XAML files are not converted in to BAML.When you build a Silverlight project a .xap file is created, it is just a .zip-file containing an AppManifest.XAML and all resources in your project compiled as dll's.  You can verify that by opening a dll in dotPeek or Reflector, it will show the XAML-files and other resources.

Thursday, February 13, 2014

Async task helper


Here is a simple helper class for async tasks. The helper class encapsulates code for creating task, This is a very interesting way to isolate the complexity of task programming. Class implementation is nothing much fancy, Async and await keywords are only used in the helper class so our main code remains very clean. The method DoAsync accepts three parameters, one function and two action. First is the function that is the actual work or task we want to accomplish asynchronously, second action is fired when the work is completed successfully and the third parameter is a action that is fired in case of an exception.

   1: using System;
   2: using System.Threading.Tasks;
   3:  
   4: namespace Common.Helper
   5: {
   6:     public class TaskHelper
   7:     {
   8:         public static void DoAsync<T>(Func<T> work, Action<T> completed, Action<Exception> exceptionHandler)
   9:         {
  10:             Task<T> task = AsyncTask(work);
  11:             task.GetAwaiter().OnCompleted(() =>
  12:             {
  13:                 if (task.IsFaulted)
  14:                     exceptionHandler(task.Exception);
  15:                 else
  16:                     completed.Invoke(task.Result);
  17:             });
  18:         }
  19:  
  20:         private static async Task<T> AsyncTask<T>(Func<T> func)
  21:         {
  22:             return await Task.Run(func);
  23:         } 
  24:     }
  25: }

 

Below is a very simple class that utilize TaskHelper. Assuming that we are using the class in a UI application to perform some lengthy work, once the work is complete we want to display some data to the user. The method DoWork is suppose to perform the lengthy work and return the result as a string value. Once the work is finish the method WorkCompleted will be invoked, if there are any exception during this process the method HandleException should handle and display proper error to the user.

 


   1: public class SomeTask
   2: {
   3:     public SomeTask()
   4:     {
   5:         TaskHelper.DoAsync<string>(DoWork, WorkCompleted, HandleException); 
   6:     }
   7:     private string DoWork()
   8:     {
   9:         return "TaskDone";
  10:     }
  11:     private void WorkCompleted(string status)
  12:     {
  13:     }
  14:     private void HandleException(Exception ex)
  15:     {               
  16:     }
  17: }