Reflection From a DLL and Serialization

Last week, we finished up our main series on reflection.  For most people, what we covered is all they will ever need.  However, there are a few other things I’ve needed to know due mainly to the fact that I was using reflection from a DLL instead of an EXE

When I wrote VSS.NET, which was my first .NET application, allow Visual SourceSafe to be used over the Internet, I wanted to implement the SCC api.  This is the API that allows you to use VSS from the IDE.  For some reason that I can’t remember now and isn’t important to this discussion, I needed to use reflection from the DLL that the SCC interface was calling.  This posed two problems.

Reflection From a DLL
First, because the DLLs were being called from an unmanaged DLL that might be called from ANY EXE (VB6, Visual Studio 6, Visual Studio 2002, etc) I needed some way of loading the reflected DLLs from where the main DLL was located, or I needed to go through the trouble of putting the managed DLLs in the GAC.  I opted to load them based on the directory the unmanaged DLL was in.  For this, you’ll need to use Assembly.LoadFrom() instead of Assembly.Load().

That was easy enough to fix.  But, the second issue I ran into took me quite a while to track down.

Using Serialization and Reflection from a DLL
You see, my main DLL was serializing the configuration settings to a file and needed to deserialize that information when the main object was created.  Buried deep in the documentation is the fact that when you use Serialization, .NET will look for the DLLs and objects based on the location of the EXE, even if you’ve already loaded the DLLs into memory.

This means that if the DLLs you are reflecting are in a different directory, you’ll never be able to deserialize the object from the file!

There is a solution.  .NET provides an event handler off the current Appdomain that you can access via, System.AppDomain.CurrentDomain.AssemblyResolve.  The AssemblyResolve event fires when .NET can’t find the proper DLL for an assembly it is trying to load.

So, all you need to do is provide a function that loads the DLL from the right location, and returns the Assembly object.

If you’ve already loaded the assembly, all you have to do is find the assembly in the current app domain and return it.  So, my event handler looks like this:

public static Assembly MyResolver(Object sender,ResolveEventArgs args)
{
    // Get all of the loaded assemblies
    Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies();
    // Get the name of the assembly we need to return
    String name = args.Name.ToUpper().Substring(0,args.Name.IndexOf(","));
    // If it is this assembly, just return this assembly
    if(args.Name.StartsWith("VSS_NET,"))
        return Assembly.GetExecutingAssembly();
    // Otherwise, find the assembly in the list of 
    // assemblies.
    foreach(Assembly asm in Assemblies)
    {
        if(asm.FullName.ToUpper().StartsWith(name))
            return asm;
    }
    // if we still haven't found it, use load from and load
    // from the same directry this dll is in.
    String currentLocation = Assembly.GetExecutingAssembly().Location;
    Assembly newAsm = 
      Assembly.LoadFrom(currentLocation.ToUpper().Replace("VSS_NET",name));
    return newAsm;
}

 

All that is left is to wire up the event handler prior to deserializing:

System.AppDomain domain = System.AppDomain.CurrentDomain;
domain.AssemblyResolve += new ResolveEventHandler(VSSController.MyResolver);

Related Post

  • Serializable attribute vs Serializable InterfaceSerializable attribute vs Serializable Interface Judging from the comments I received yesterday, it looks like we need to review  serialization in .NET. The Easy Way There are two ways of making an object serializable.  The first, and eas...
  • Reflection -The ConstructorReflection -The Constructor Remember, last week we started a series on using Reflection in our .NET applications.  We've loaded the assembly already, so the next step is creating the object.  Today's tutorial will show how to...
  • DotNetNuke Modules – Creating Base ModulesDotNetNuke Modules – Creating Base Modules Now that we have DotNetNuke installed into Visual Studio we can go ahead and create our first modules. Actually, creating the modules is pretty simple. But it is even easier to do it wrong, which...
  • Reflection – Loading The AssemblyReflection – Loading The Assembly Recently, I received a question from a web visitor asking me to cover reflection.  So, I'm going to start a series on reflection.  Remember, if you have any questions you can ask me using...
  • Reflection and InterfacesReflection and Interfaces Today is the last official installment in the series on reflection.  If you've been following along, you've probably notice that calling code in other classes using reflection is a huge pain i...
  • http://www.conqueredpasture.com ramil

    Thanks for sharing these stuff.