Reflection

J

Jozsef Bekes

Hi All,

I am trying to use reflection for getting all the classes from the dlls of a
software written by my company. I am using this line:

Assembly.LoadFile(s).GetTypes()

Gettypes fails, I guess because when one dll refers to another one of mine,
Reflection does not find that dll. This is what the exception contains
anyway. So I realized that I'd need to copy the dlls, or register them to
the GAC. And then I tried Reflector, and to my amazement, everything was
working fine! Then I tried some tricks, invoked Assembly.LoadFile() for all
the referenced dlls before trying GetTypes() on the one in question, still
no success. Does anyone have an idea how it can be done without copying and
GAC?

I appreciate all your answers.

Thanks,

Jozsi
 
L

Leon Lambert

Try this before you load and see if it helps.
String path = Path.GetDirectoryName(Path.GetFullPath(assemblyName));
#if VS2003
AppDomain.CurrentDomain.AppendPrivatePath(path);
#else
AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = path;
#endif

Hope it helps
Leon Lambert
 
J

Jozsef Bekes

Hi Leon,

thank you for the suggestion. I could not manage to make it work even with
the lines you suggested, but this might also be needed for making the stuff
run.

Thank you,
Jozsi
 
L

Leon Lambert

Was hoping to avoid this but here is a more complex way to try.
First define a ResolveEventHandler in the class where you are doing the
loading. It would look something like the following. Sorry for ugly
look. This UseNet Reader is wrapping stuff

private ResolveEventHandler resolveEventHandler;

Then somewhere before you try to load add a handler. Something like this.

resolveEventHandler = new ResolveEventHandler(AssemblyResolver);
Thread.GetDomain().AssemblyResolve += resolveEventHandler;

Then create a resolver method something like this.
In my case i had a command line argument to specify
additional directories where to search for support
dlls. So the handler will also search there.
public Assembly AssemblyResolver(Object sender,ResolveEventArgs args)
{
String path;
// try looking in same directory as the original one first

// assembly is a class variable containing the starting loaded
// assembly

// assemblyNameToResolve is a class string variable.

path=assembly.Location.Substring(0,assembly.Location.LastIndexOf("\\") + 1);
assemblyNameToResolve = args.Name;
if ((assemblyNameToResolve.IndexOf(",") != -1) &&
(assemblyNameToResolve.IndexOf("Culture") != -1))
assemblyNameToResolve=assemblyNameToResolve.Substring(0,assemblyNameToResolve.IndexOf(","));

// I had a collection of loaded assemblies.
// This check to see if i already loaded it and just
// return it if it was already loaded
Assembly assm = assembliesLookup[assemblyNameToResolve] as Assembly;
if (assm != null)
return(assm);
try
{
assm =
Assembly.LoadFrom(String.Concat(path,assemblyNameToResolve,".dll"));
}
catch (Exception)
{
}
// if not found try looking in directories passed in
// as command line arguments
if (assm == null)
{
foreach (String assemblyPath in extAssemblyDirectory)
{
try
{
assm =
Assembly.LoadFrom(String.Concat(assemblyPath,assemblyNameToResolve,".dll"));
if (assm != null)
break;
}
catch (Exception)
{
}
}
}
if (assm == null)
throw(new Exception("Cant find assembly " +
assemblyNameToResolve));

// add to collection of already looked up assemblies
assembliesLookup.Add(assemblyNameToResolve,assm);
return(assm);
}

When done using the loading class add the following code to remove the
handler.

Thread.GetDomain().AssemblyResolve -= resolveEventHandler;

This should work because it did for me. Sorry for the ugliness because
of line wrap
Leon Lambert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top