Question

I have an assembly I'm trying to load with reflection and read a Resource string from.

So, I use something like this:

        config.Extras="C:\dev\foo.dll";
        string dir = Directory.GetCurrentDirectory();
        string tmp = Path.GetDirectoryName(config.Extras[0]);
        Directory.SetCurrentDirectory(tmp);
        var asm = Assembly.LoadFile(config.Extras[0]);
        foreach (var item in asm.GetManifestResourceNames())
        {
                ResourceManager rm = new ResourceManager(item, asm);
                string foo=rm.GetString("foo"); //error here
        }

However, this throws a FileNotFoundException because it can't find a referenced assembly of foo.dll. Foo.dll has a dependency on Bar.dll. It throws the error saying it can't find bar.dll. The actual location of bar.dll though is in the same directory as foo.dll.

So, how do I resolve this error?

Was it helpful?

Solution

The Load methods in the Assembly class suffer from a naming problem. Nobody ever gets Load() wrong. But LoadFile() has a much too attractive name. LoadFrom should have been LoadFile and LoadFile should have been LoadButUseThisOnlyWhenYouReallyKnowWhatItDoes().

The loading context for an assembly is difficult to understand. Suzanne Cooke has blogged about it a lot, not otherwise putting much of a dent into explaining it :) Roughly, when you use LoadFile, the CLR does not keep track of where the assembly came from and won't stop you from loading the assembly more than once. The types in that assembly are unique and the same type loaded from two LoadFile calls are not identical. You only ever use LoadFile when you intentionally don't want a match. The kind of thing that programs that read metadata would be interested in, a decompiler for example.

The "does not keep track of where the assembly came from" clause is the problem here. You need to use LoadFrom().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top