We all know that the assembly can be queried for attributes using the GetCustomAttributes method. I want to use this to identify an extension module for my application. However, to avoid loading every assembly I prefer a defensive approach:

using Assembly.ReflectionOnlyLoadFrom to get more details about an assembly (has it my ModuleAttribute?)

if the ModuleAttribute is found, I will finally load it using Assembly.LoadFrom

Unfortunately it seems that there is no way to get the attributes from an assembly, that is loaded into the reflection-only context:

myAssembly.GetCustomAttributes(typeof(ModuleAttribute), false)

fails with an InvalidOperationException ("It is illegal to reflect on the custom attributes of a Type loaded via ReflectionOnlyGetType") and

CustomAttributeData.GetCustomAttributes(myAssembly)

fails with ReflectionTypeLoadException because of dependant assemblies not being loaded.

Can you elaborate with a better answer here? It sounds like you found a work around... But I can't make it work.
–
VaccanoNov 15 '11 at 22:30

1

This is not a workaround but a valid solution. When the assembly containing the required types cannot be discovered in reflection-only context, the ReflectionOnlyAssemblyResolve event is fired. You can manually load the assembly then.
–
paulius_lOct 8 '12 at 14:23

After checking all answers and doing some more research, it seems that there is simply no way to do what I want: check if an assembly is a valid extension module before loading it into the application domain.

Either I have to load the assembly that should be inspected into another application domain, inspect it there and when it succeeds load it again into my current application domain or I need to store metadata of the assembly outside the assembly itself and trust this metadata. Option one is not possible because of architectural restrictions, option two just shifts the problem but not solves it.

Probably the best alternative is to use the Managed Extensibility Framework, but this is unfortunately not that easy in the current setup.

I end up with trusting that there is nothing "bad" in the modules directory and loading everything (with some checks for not exceeding a maximum file size and not being loaded already).

MAF or even MEF seems to be an option, yes. Unfortunately this would require a change in the design of the plugin, which is not directly (and not mandatory) developed by us.
–
Marc WittkeSep 22 '09 at 12:04

It could be a problem if the plugin isn't easily wrapable
–
monkey_pSep 22 '09 at 12:10

But i suppose wraping it would defy your need if the external plugins need to be recompiled by you
–
monkey_pSep 22 '09 at 12:11

If I were you I'd cache assembly metadata in, for instance, XML files. Using this approach you completely eliminate a need to load anything. And you can store even information, to calculate which you need to perform a time-consuming operation.

You can have XML files pregenerated or generated on-the-fly by scanning all existing assemblies.

Don't like this approach, because it relies on additional metadata. This is not much better than hard coding in which directory an assembly with fixed file name must be located.
–
Marc WittkeSep 22 '09 at 12:06

It relies on cached metadata, not additional. You extract metadata from assemblies and store them in your cache (XML files or whatever). It is faster and better then reading assemblies. Also, this approach is much more extensible because after some time you will end up with something, you will not be able to extract from assembly without loading it.
–
FractalizeRSep 22 '09 at 12:41

Maybe I don't get you, but who is creating the metadata cache? It requires either the creator to provide a valid metadata description or me to create it somewhat earlier before attempting to load the module. In both ways, someone will need to do this and the problem is exactly the same
–
Marc WittkeSep 23 '09 at 8:02

"or me to create it somewhat earlier before attempting to load the module" - YES. And you need to do that just once. For example, during software installation. After that there is no performance impact as you read metadata from the cache you generated.
–
FractalizeRSep 23 '09 at 8:24