AssemblyResolve FileNotFoundException, Load Assembly from resource

By admin - Last updated: Friday, September 18, 2009 - Save & Share - Leave a Comment

I was struggling with this issue while I was trying to load the referenced assembly stream from the resource.
It was caused by JIT (Just In Time compiler) tries to resolve the assembly before the CLR actually executes the AssemblyResolve assignment.

You may have the code looks like this

static void Main(string[] args)
{

    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.AssemblyResolve += (sender, args2) =>
    {

        string name = new AssemblyName(args2.Name).Name;

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(“EmbedDll.” + name + “.dll”))
        {
            if (stream != null)
                return Assembly.Load(new BinaryReader(stream).ReadBytes(0x1e8480));
        }

        return null;
    };

    // use stuff from the assembly that we need to resolve
    ClassElseWhere obj = new ClassElseWhere();
    obj.DoThing();

    Console.ReadKey();
}

This will fail even you have currentDomain.AssemblyResolve += (sender, args2).. defined as the first line of the method. However when JIT compiler hits Main(string args) method, it will try to resolve all the referenced assemblies immediately. Therefore it will try to look for dll containing ClassElseWhere class. Right at that point the AssemblyResolve delegate has been assigned yet, so JIT has no other clue to find the dll and simply it just throws the exception.

Solution
Place delegate assignment code into the scope which gets executed earlier, say in the constructor or static constructor.

Or by utilizing JIT compiler lazy loading characteristic, place the code which references the external dll into different method.

Here is the code I made work

static void Main(string[] args)
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    // this gets executed before it tries to resolve
    // the dll
    currentDomain.AssemblyResolve += (sender, args2) =>
    {
        string name = new AssemblyName(args2.Name).Name;

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(“EmbedDll.” + name + “.dll”))
        {
            if (stream != null)
                return Assembly.Load(new BinaryReader(stream).ReadBytes(0x1e8480));
        }
       
        return null;
    };

    // JIT doesn’t need to resolve the
    // the dll at this point within main()
    DoThing();

    Console.ReadKey();
}

// when JIT executes here
// it’ll try to resolve the dll
static void DoThing()
{
    var foo = new ClassElseWhere { Name = “test” };
    foo.Print();
}

JIT compiler executes the AssemblyResolve assignment prior to trying to resolve assembly containing ClassElseWhere class because code containing ClassElseWhere is located in the other method rather than the one containing the AssemblyResolve assignment. Therefore JIT compiler wouldn’t need to find where the dll containing ClassElseWhere class when it executes the method main.

Happy coding 🙂




Posted in Code Notes • Tags: Top Of Page

Write a comment


Captcha: 2 × four =