Checking for add-ins in an assembly

Aug 26, 2008 at 12:58 AM

In our application, we include a mechanism for users to supply DLLs (or ZIP files containing DLLs) to the system, which provides a distribution mechanism for the add-in.

I would like to check the DLL when the user provides it to confirm that it does indeed contain add-ins.  (And if it's a ZIP file that contains multiple DLLs, I'd like to confirm that one and only one of them contains add-ins.)  I thought that I could do this using Assembly.ReflectionOnlyLoadFrom - load up the assembly and iterate through the types looking for the AddIn attribute.  Unfortunately, ReflectionOnlyLoadFrom does not resolve all the references.  The documentation led me to believe that <mshelp:link tabindex="0" keywords="Overload:System.Reflection.CustomAttributeData.GetCustomAttributes">CustomAttributeData.GetCustomAttributes could still be used in this circumstance, but it doesn't work (maybe because the custom attribute is defined in another assembly?)  After some time spent trying to load manually load the required assemblies, I decided I didn't want to rewrite the loader.  I'm hoping there's an easier way that I just overlooked.

Also, once you have loaded an assembly into the reflection-only app domain, is there an easy way to unload that app domain?  When I couldn't actually get the custom attributes, I settled for just checking to make sure the assembly referenced my add-in views assembly.  I can load the assembly and check the references, but once I'm done, the DLL is locked by the app until it exits.  I would really like to free it up.


Thanks,
Bob Wall

</mshelp:link>
Aug 26, 2008 at 9:44 AM
Hi Bob,

If you do your reflection-only loading in a separate AppDomain, you should just be able to hook up a handler to the AppDomain.ReflectionOnlyAssemblyResolve event.

HTH,
Kent
Aug 26, 2008 at 7:28 PM
Hi Bob,

For the AddInStore Rebuild/FindAddIns methods, we provide overloads that can take in directories for add-ins and the pipeline root. You can unzip the add-in to a temporary folder, pass that to the AddInStore methods, and see if it can find any add-ins. This lets you avoid having to do reflection-only loads and worrying about assembly resolve events. In fact, letting users avoid the trouble of rewriting the loader is one of the reasons the add-in framework exists.

Thanks,

-Mueez
Aug 26, 2008 at 7:49 PM
I had thought of that ... I was hoping for something a little easier, because as far as I've been able to tell so far, you need to pass a specific type to FindAddIns.  I have 22 different add-in interfaces defined so far, and as far as I can see, I'd need to call FindAddIns on each of those types to see if the file contained that type.

This is still way easier than handling the AssemblyResolve events - it's easy enough to set up the code to catch them, but then figuring out where to find the referenced assemblies to load is a bit of a pain.  I'm hoping there's something easy that I overlooked that will allow me to check for any type of add-in in the assembly.


Thanks,
Bob

Aug 26, 2008 at 10:38 PM
You can always define a base contract and have the 22 interfaces derive from that one. That would make finding add-ins easier for the host.
Aug 26, 2008 at 10:43 PM
Good point - and it turns out that I've actually already done that anyway.  Wasn't thinking too quickly there...

This actually works well - FindAddIns doesn't lock the DLLs the way that loading them into a reflection-only app domain does (or rather it probably does, but then deletes the app domain).

Thanks!
Bob
Aug 27, 2008 at 1:31 PM
Wow, what was I thinking? Sorry Bob, and thanks Sid.

FYI, I've done the same thing with the inheritance hierarchy and it works well. And although you use the base interface to find the add-in, MAF still allows you to activate it with a derived interface type.

KB