CLR 4.0: Type Embedding

Note: This Post transfered from my OLD Blog and was originally posted in 2008.

 

As new enhancement in CLR version 4.0 (will be released in 2010) is the concept of Type Embedding. The actual motivation for this new concept was the miserable story of deploying application that uses Primary Interop Assemblies (PIA).

In previous versions of CLR you’ve needed to deploy your managed assembly plus the PIA to the client machine, in some scenarios like developing against the MS Office’s PIAs, you need to deploy the whole Office PIA Redist which is about 6.3 MB to make your little application works!!

and the problem getting worth if you try to target a machine that have different version of MS Office’s PIAs

This was a very bad experience if you have been through it before.

image

So the Scenario was trying to develop against PIAs leads to:

  • Complex deployment scenarios
  • Targeting multiple hosting environment.
  • Tight type coupling.

MS started a new project code-name NOPIA as part of the next version of CLR 4, its target was to eliminate runtime dependency on Interop Assemblies at compile time easily, So you can do that with just flipping a switch in the visual studio assembly reference properties window or just by compiling your code with /link switch.

What’s NOPIA

Using this new capability you are actually telling the CLR to embed all the necessary information to call the com object embedded into the managed assembly itself, so you don’t need the PIA assembly to be deployed with your application anymore.

The embedded information represented as “Local Types” which is a partial copies of the types exist in the PIA.

As an example we will develop this sample Hello Buddy console Application simply takes a name and interact with Word PIA ( Microsoft.Office.Word.dll ) from Office PIA Redist, to create new word document and Write “Hello name” statement.

image

I’m using Visual Studio 2010, .Net 4.0, and CLR v4.0 CTP to develop this application, you can download this CTP here.

  • Create new C# console application.
  • Add reference for Microsoft.Office.Interop.Word.dll
  • Add this class to your applicaion.
 1: using System;
 2: using Word = Microsoft.Office.Interop.Word;
 3:
 4: namespace HelloBuddy
 5: {
 6:     public class Program
 7:     {
 8:         static void Main(string[] args)
 9:         {
 10:             SayHi("Ahmed");
 11:             Console.ReadLine();
 12:         }
 13:
 14:         public static void SayHi(string name)
 15:         {
 16:             Word.Application wordApp = new Word.Application();
 17:
 18:             wordApp.Visible = true;
 19:             wordApp.Activate();
 20:
 21:             object falseValue = false;
 22:             object trueValue = true;
 23:             object missing = Type.Missing;
 24:
 25:             Word.Document doc = wordApp.Documents.Add(ref missing, ref missing, ref missing, ref missing);
 26:
 27:             object start1 = 0;
 28:             object end1 = 0;
 29:
 30:             Word.Range rng = doc.Range(ref start1, ref missing);
 31:             rng.Font.Name = "Tahoma";
 32:             rng.InsertAfter("Hello " + name);
 33:
 34:         }
 35:
 36:     }
 37: }
  • Compile and run
  • You should be apple to see MS Word window open with “Hello Ahmed” statement.Check the compiled assemblies in your bin directory, you’ll find:
    1. HelloBuddy.exe
    2. Microsoft.Office.Interop.Word.dll.

    Attach “HelloBudy.exe” to your VS Debugger, and check the loaded modules, you will find the Office PIA assembly is loaded, and this is the one we are trying to get rid of

image

loadedModules1NOPIA Mode

Now let’s switch to NOPIA Mode, and embed those PIA used types into our console assembly, to do that:

  • Select the PIA assembly reference and choose properties
  • In Properties window, change property “Embed Interop Types” to True
  • Recompile your application.

If you check the Bin directory you will find only the application assembly ”HelloBuddy.exe ”, there is no PIA assembly. The Only difference is application assembly becoming little bit bigger because it now embed the partial type info from the original PIA, but still smaller than deploying the whole PIA file.

Attach “HelloBudy.exe” to your VS Debugger, and check the loaded modules, you will find only your application assembly, no more PIA.

Behind the Scene

If you are interested to know what actually CLR do behind the scenes, open your application assembly with Reflector and check the types inside it, you will find that CLR has injected Microsoft.Office.interop.Word namespace into your application’s assembly.

embed
In this namespace you can find only the set of types “local types” that you have used from the PIA into your application. Types like  Application, Document, Range, Font.
In fact the CLR rips only the types necessary to complete the calls you have made from your application, More than that if you check the emitted code for those types, for instance the Application type. CLR extracted only the functions you have called and replaced all the other functions and Type members with the magic _VblGap calls. Those _VtblGap pseudo methods are emitted in place of unused methods to maintain vtable compatibility.
embedIL0

NOPIA Limitations

Ofcourse there is nothing without limitations. NOPIA has some limitation of what you can embed into your assemblies:

  1. Can’t Embed IL (no classes or static methods)
  2. Only metadata is locally embedded (interfaces, delegates, enums, structs )
  3. Only types from Interop Assemblies can be embedded. Compilers check for these attributesa. [assembly:Guid(…)]b. [assembly:ImportedFromTypeLib(…)]

As you can see how the MS Future CLR v4.0 provides an easy way to develop application against COM interop assemblies, along with very friendly, powerful deployment scenario.

Related stuff

Hope this helps,

Ahmed