8

I'm trying to load a few modules via hooking into the AppDomain.AssemblyResolve and AppDomain.ReflectionOnlyAssemblyResolve events. While I got the former to work, I fail miserably on the latter. I've boiled my problem down to this little program:

public static class AssemblyLoader
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += 
            ReflectionOnlyAssemblyResolve;

        // fails with FileNotFoundException
        Assembly.ReflectionOnlyLoad("Foo");
    }

    public static Assembly ReflectionOnlyAssemblyResolve(object sender, 
        ResolveEventArgs args)
    {
        Trace.TraceInformation(
            "Failed resolving Assembly {0} for reflection", args.Name);

        return null;
    }
}

Running this program fails with a FileNotFoundException when trying to Assembly.ReflectionOnlyLoad, but it doesn't call the ReflectionOnlyAssemblyResolve handler. I'm pretty stumped there.

Does anybody have an idea what could be the root cause of this and how to get this to work?

Thanks!

starblue
  • 55,348
  • 14
  • 97
  • 151
David Schmitt
  • 58,259
  • 26
  • 121
  • 165

3 Answers3

8

It would appear that the ReflectionOnlyAssemblyResolve event is only used to resolve dependencies, not top-level assemblies, as indicated here:

http://codeidol.com/csharp/net-framework/Assemblies,-Loading,-and-Deployment/Assembly-Loading/

And here:

http://blogs.msdn.com/junfeng/archive/2004/08/24/219691.aspx

casperOne
  • 73,706
  • 19
  • 184
  • 253
1

Expanding on casperOne's answer.

If you want to intercept direct Assembly Resolve events you need to hook into the AppDomain.AssemblyResolve event. This is a global hook though so it alone won't fit your scenario. However if your application is single threaded you could a short term hookup in order to intercept specific resolve events.

static void LoadWithIntercept(string assemblyName) {
  var domain = AppDomain.CurrentDomain;
  domain.AssemblyResolve += MyInterceptMethod;
  try {
    Assembly.ReflectionOnlyLoad(assemblyName);
  } finally {
    domain.AssemblyResolve -= MyInterceptMethod;
  }
}

private static Assembly MyInterceptMethod(object sender, ResolveEventArgs e) {
 // do custom code here 
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • AssemblyResolve is not triggered when using ReflectionOnlyLoad(). As I came to understand, this is by design, to avoid loading assemblies that are not "wanted" by the user of ReflectionOnlyLoad(). I'm not yet sure if I completely agree with that point of view though. – David Schmitt Feb 20 '09 at 17:17
0

You can force it by calling ExportedTypes on the assembly like this:

var dummy = asm.ExportedTypes;

So if you want to load an assembly with all its referecnes recursively:

 private void _forceAssemblyResolve(Assembly asm) { var dummy = asm.ExportedTypes; }

 var result= Assembly.ReflectionOnlyLoad("Foo");
 _forceAssemblyResolve(result);

public static Assembly ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
    var childAssembly = _resolve(args);
    _forceAssemblyResolve(childAssembly);
}
CSharpie
  • 9,195
  • 4
  • 44
  • 71