ILMerge alternative with embedded resources for class library

In my previous post I pointed out how to implement the Jeffrey Richter alternative to ILmerge on WPF applications. Now I want to show you how to do this with class libraries using module initializers tool from Einar Egilsson.

Again the idea is to add all referenced assemblies as embedded resources and load them when they are needed. But a class library has no constructor or initializer in the world of C#. Where to register the AssemblyResolve eventhandler? According to Einar Egilsson’s post you can add a module initializer by injecting IL code into the assembly. The framework supports module initializers, which are called before any other code from the module (assembly) is executed, when the assembly is hit for the first time.

First add the assemblies from the references as embedded resources (see previous post for details)

Then create a public parameterless static void method. This will be called from the module initializer,

/// <summary>
/// Run on first construction of this module
/// </summary>
public static void Run()
{
   AppDomain.CurrentDomain.AssemblyResolve += (s, a) =>
   {
      // construct resource key from type name and namespace
      var name = new System.Reflection.AssemblyName(a.Name).Name;
      var resourceName = string.Format("YOUR_NAMESPACE.Resources.{0}.dll", name);
      // lookup the embedded resource for the requested type
      using (var stream = System.Reflection.Assembly.GetAssembly(typeof(YOUR_CLASSNAME))
                                                    .GetManifestResourceStream(resourceName))
      {
        if (stream != null)
        {
            // load assembly from embedded resource
            var assemblyData = new Byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return System.Reflection.Assembly.Load(assemblyData);
        }
        else
        {
           // Embedded resource not found
           System.Diagnostics.Trace.TraceError("Unable to locate resource {0}", resourceName);
           return null;
        }     
     }
  };
}

Notice the YOUR_NAMESPACE and the Resources after that. The assemblies are in the Resources folder and that will be part of the name of the embedded resource. Different from my previous post load the assembly containing YOUR_CLASSNAME type as it will not be the ExecutingAssembly.

TIP: add a console application with tracelistener to you solution to figure out the unresolved resources

Add a postbuild step to the project that injects the module initializer. You can download InjectModuleInitializer from Einar Egilsson‘s site.

<Target Name="AfterBuild">
  <Exec Command='InjectModuleInitializer.exe /m:YOUR_NAMESPACE.YOUR_CLASSNAME::Run "$(TargetPath)"' />
</Target>

I was able to use this in an ASP.NET webapplication. Zip file with solution and projects download. Thumbs up!

About erictummers

Working in a DevOps team is the best thing that happened to me. I like challenges and sharing the solutions with others. On my blog I’ll mostly post about my work, but expect an occasional home project, productivity tip and tooling review.
This entry was posted in Development and tagged , , , , , , , , . Bookmark the permalink.

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 )

Facebook photo

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

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.