Yes, I’ve raised this with the MEF team many times. It’s easier to go and do it yourself.

The issue is that DirectoryCatalog does not guard against failures on loading types (which is quite common as soon as you start working on real projects as opposed to samples – hint hint!). So here’s a better version (in F#):

    type DirectoryCatalogGuarded(folder) = 
        inherit ComposablePartCatalog()
        let _catalogs = List()
        let mutable _parts : ComposablePartDefinition seq = null
        let load_assembly_guarded (file:string) = 
            try
                let name = AssemblyName.GetAssemblyName(file);
                Assembly.Load name
            with | ex -> null
        let guard_load_types (asm:Assembly) =
          try
              asm.GetTypes()
          with | :? ReflectionTypeLoadException as exn -> exn.Types
        do 
            let files = Directory.GetFiles(folder, "*.dll")
            for file in files do
                let asm = load_assembly_guarded file
                if asm <> null then
                    let types = guard_load_types(asm) |> Seq.filter (fun t -> t <> null) 
                    if not (Seq.isEmpty types) then
                        _catalogs.Add (new TypeCatalog(types))
            _parts <- _catalogs |> Seq.collect (fun c -> c.Parts) 
        override x.Parts = _parts.AsQueryable()
        override x.GetExports(definition) = 
            _catalogs |> Seq.collect (fun c -> c.GetExports(definition))

The “trick” is to catch ReflectionTypeLoadException – something I learned from David. This exception gives you a list of types it was able to load. Mind you, nulls may exists in the list hence the filtering.

The shortcoming here is that by bypassing the AssemblyCatalog, you wont be able to use CatalogReflectionContextAttribute – which I believe I’m one of the ten people on earth that knows what it’s for, so no biggy I guess?

2 Comments

  1. Daniel Plaisted says:

    I think the reason we don’t guard against this is because the problem is missing dependencies, and catching ReflectionTypeLoadExceptions from Assembly.GetTypes() won’t help you if you have a dependency in a method implementation that isn’t exposed in the public surface. In that case you will get a FileNotFoundException the first time you run the method.

  2. hammett says:

    and I believe this is just your corpus callosum coming up with an explanation for it :-)

Leave a Reply