I am trying to use the CurrentDomain.AssemblyResolve
event to load a DLL that is marked as an Embedded Resource. My problem, specifically, comes from the fact that I am trying to use the assembly as a subclass, like so:
#define BROKEN
using System;
using System.Reflection;
using TestCompanyInc;
namespace TestConsole
{
#if BROKEN
// This is how I NEED to use it
class Program : SubClass
#else
// This is only here as a test to make sure I wired
// CurrentDomain.AssemblyResolve correctly
class Program
#endif
{
static int Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
{
string resourceName = Assembly.GetExecutingAssembly()
.GetName().Name
+ "." + new AssemblyName(eventArgs.Name).Name + ".dll";
Console.WriteLine("About to lookup {0}", resourceName);
using (var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream(resourceName))
{
byte[] assemblyData = new byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
Program p = new Program(args);
return p.Run();
}
public Program(string[] args)
{
}
public int Run()
{
#if BROKEN
// This is how I NEED to use it
Console.WriteLine(TestProperty);
#else
// This is only here as a test to make sure I wired
// CurrentDomain.AssemblyResolve correctly
SubClass sc = new SubClass();
Console.WriteLine(sc.TestProperty);
#endif
Console.ReadKey();
return 0;
}
}
}
The test class SubClass
is defined as:
namespace TestCompanyInc
{
public class SubClass
{
public SubClass()
{
TestProperty = "Init'd";
}
public string TestProperty { get; set; }
}
}
If the first line #define BROKEN
is left uncommented, then the CurrentDomain.AssemblyResolve
event will never fire and System.IO.FileNotFoundException is thrown and I am told that SubClass
can not be found. If the first line is removed or commented out, then it will fire the event (but I can't use it this way).
I have also tried moving Main
into its own class instead of having the same class create an instance of itself, but I get the exact same exception.
So, how do I get this event wired up correctly so it will load this assembly under these conditions?
Compiled in VS 2010 .NET 4, if that makes a difference to anyone. Also, for anyone trying to recreate this. SubClass is in its own project. Add SubClass as a Reference to TestConsole and mark it as Copy Local = False. I have read, somewhere, that this can not be a Project Reference, but a direct reference to the DLL. Then, add the DLL file to the TestConsole project and mark it as an Embedded Resource, not the default of Content.
Think about load-order... In order to JIT and invoke Main, it must understand Program. It can't understand Program without loading the base-class, which needs special handling. The event doesn't fire because it hasn't registered yet (because Main hasn't started).
That cannot work. The only way you can do this is to have an entry-point that doesn't depend on anything else. Note that JIT is done before the method starts, so the Main also can't involve anything that isn't known. For example, you might do:
class Loader {
static void Main()
{
// not shown: register assemy-load here
MainCore();
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void MainCore()
{ // your class as shown is Program
Program.Init();
}
}
Note we need 2 methods above since it can't JIT Main unless it can fully resolve Program. With the above, the event should fire just before MainCore() is invoked (I.e. During JIT for MainCore).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With