Hacking into the heart of a LightSwitch application.

I received an email a couple of weeks ago, in which one consultant to another mentioned “LightSwitch or another code generation tool”…
Although it is true that LightSwitch generates code for you, a running LightSwitch application contains only a really small amount of generated code.
Like any MVVM application, the heart of the application is the model.
In LightSwitch, this heart is called the application model. When you debug through a LightSwitch application, you can investigate this application model and see that it is “nothing more” then a big dictionary with over 800 entries for even the simplest application.

Since this is the heart of any LightSwitch application, it’s important to understand how this dictionary is filled, and where it is used…

The LightSwitch application model.

The application model is a combination of three major parts that I’m aware of…

  • Core: Multiple LSML files (xml compliant documents called “LightSwitch Markup Language” files) hidden in the LightSwitch internal assemblies.
  • Extensiblity: multiple LSML files from different modules. Each time you create an extension, a file called module.lsml is added along with a ModuleLoader implementation that loads that file. Extensions are not the only modules that provide input for the application model though, LightSwitch comes with a Security module (users, rights, user groups, …) which is also a module, and so is your LightSwitch application itself!
  • Application: the latter, your LightSwitch application, contains a file called ApplicationDefinition.lsml.

The application model is used in three different places as well:

  • Runtime: obviously, as stated before, it’s the heart of your running application.
  • Compile time: from the data in your appication model, the LightSwitch framework generates everything from classes to config to the database (Entity Framework).
  • Design time: this may sound a bit weird, but the LightSwitch specific screens in visual studio, aren’t much more than advanced graphical XML (LSML) editors…

LSML editor: all screen definitions are found in the different modules that form the application definition

 

LSML editor: all screens and data sources are found in the different modules that form the application definition

 

LSML editor: all properties are found in the different modules that form the application definition

Ok, enough theory, time to get our hands dirty.

The basic idea is simple: if, during the installation of our extension, we can get our hands on the ApplicationDefintion.lsml file, we can add anything we want to the LightSwitch application…

If you wonder why we want to do this, the reason is simple.  We want to create a skinning extension that is capable of storing user specific skin configurations and need a better alternative than the LightSwitch default implementation.

Before I show you this ugly hack (and man o’ man, it’s one of the ugliest pieces of code I have probably ever written…), a word to the wise: with great power comes great responsibility.  It is really easy to corrupt the file, and thus destroying the developer’s LightSwitch application.  Don’t hold me responsible if you though…  Also, if LightSwitch releases a new version, the implementation might be subject to change, so having your crucial business needs depend on this hack is a bad idea.

Right, let’s get to it.  The perfect place to implement our hack is the point where our extension is loaded by the Visual Studio environment.

Create a new extension (any extension will do at this point, shell, theme, user control, datasource, whatever) and have a look at the project called MyExtension.Common: there is a class called ModuleLoader.cs, which is ofcourse our prime candidate…

It contains a method called LoadModelFragments.

    [ModuleDefinitionLoader("MyExtension")]
    internal class ModuleLoader 
         : IModuleDefinitionLoader
    {
        #region IModuleDefinitionLoader Members

       /* ... */

        IEnumerable<Stream> IModuleDefinitionLoader.LoadModelFragments()
        {

Doing a bit of research, I found that this method is called indeed during both the runtime of the LightSwitch application, and at design time, by the Visual Studio LightSwitch environment.  It’s a must that we find a way to differentiate between both cases: runtime is simply too late, the database tables have been created, and corresponding classes have been generated.  We’re only interested in modifying the application definition at design time…

            Assembly assembly = Assembly.GetExecutingAssembly();
            Assembly s = Assembly.GetCallingAssembly();  
            if(s.FullName.StartsWith("Microsoft.LightSwitch.Design.Core.Internal")){

The implementation of our hack keeps getting dirtier, don’t judge my coding skills by what you saw above, and what you’re about to see below!!

At this point, we found a point in time where we are sure that the Visual Studio LightSwitch environment is loading our extension.  Before we can add our custom tables to the default dataworkspace in the application definition, and basically get a free ride from the LightSwitch framework to actually add our tables to the database and generate the model and data access classes, we must first get a reference to the ApplicationDefinition.lsml file.

Because this code resides in an extension, one can be sure that our extension has been copied to the solution’s folder called Pvt_Extensions.  Let’s backtrack the applicationdefinition file from there…

                    string assemblyUrl = assembly.CodeBase;
                    int index = assemblyUrl.LastIndexOf("_Pvt_Extensions");
                    if (index != -1) {
                        string ApplicationDefinition =
                            assemblyUrl.Substring(8, index -8) + 
                            "Data/ApplicationDefinition.lsml";
                                /* HomeWork time ... */

 

That’s all there is to it.

I kind of ran out of time here (running late for a training today), so school is out, and here’s your homework for today: to know what one needs to add to this file, create a new LightSwitch application.  Take a backup of the ApplicationDefinition.lsml file, then compare it to a version where you added a really simple table.  Try to implement this process where indicated in the code above.  There’s two more pitfalls to encounter, and I’m curious to see  how you will handle them.

Meanwhile, I’ll clean up my sample a bit and release it later this week.  As a little teaser: my sample uses similar (yet not exactly) the same technique as described above, to merge different LightSwitch applications together…

Happy fragging!

About these ads

9 thoughts on “Hacking into the heart of a LightSwitch application.

  1. Jan no need to appologize for the code hacks as always your blog postings are the most highly informative on the inner workings of LightSwitch then any I have found, very well done.

    I become excited when I see a new posting from you site arrive into my inbox because I know I am about to learn something new about LightSwitch.

    Cheers

  2. Pingback: Windows Azure and Cloud Computing Posts for 10/10/2011+ - Windows Azure Blog

  3. I tried the above approach in a different way, when I started to work on Copy/Paste extension, but ended up by creating a separate application (not an extension) and messing with LSML by inserting XML nodes here and there. It did work for a simple page, but messed completely when a screen goes more complex.

    Inserting the same nodes at runtime is something I thought ‘would be complex and for advanced users and need depth knowledge in Application Model’, like you… :).

    I hope your findings may lead someone to get this ‘copy/paste’ stuff.

    • The LSML is quite an enormous beast… Next year, I want to continue this series of hacking into it by writing on “modules”, which reduces the number of XML nodes needed to insert to: 1… Also, the application model has an API, which I want to show the world. :-)
      The worst thing is that I have about 3 samples on this ready and working, but I can’t find the time to post them / blog about it… :(
      Time has never been my friend, but I’m trying to find a better balance in my life now, which should result into more posts from me on a more regular bases! :-)

  4. Pingback: LightSwitch Community & Content Rollup–October 2011 - Technology | Zeytin.Net

  5. Pingback: What’s new in Visual Studio LightSwitch 11 (LS VS vNext Beta) – a hacker’s view… « Jan Van der Haegen's blog

  6. Pingback: Windows Azure and Cloud Computing Posts for 2/24/2012+ - Windows Azure Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s