MEF: "No se puede cargar uno o más de los tipos solicitados. Recupere las LoaderExceptions para más información "
plugins (3)
Aquí hay un ejemplo de los métodos mencionados anteriormente:
var di = new DirectoryInfo(Server.MapPath("../../bin/"));
if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName);
var dlls = di.GetFileSystemInfos("*.dll");
AggregateCatalog agc = new AggregateCatalog();
foreach (var fi in dlls)
{
try
{
var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName));
var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException
agc.Catalogs.Add(ac);
}
catch (ReflectionTypeLoadException ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
CompositionContainer cc = new CompositionContainer(agc);
_providers = cc.GetExports<IDataExchangeProvider>();
Escenario: estoy usando Managed Extensibility Framework para cargar complementos (exportaciones) en tiempo de ejecución basado en un contrato de interfaz definido en una dll separada. En mi solución de Visual Studio, tengo 3 proyectos diferentes: la aplicación host, una biblioteca de clases (que define la interfaz - "IPlugin") y otra biblioteca de clases que implementa la interfaz (la exportación - "MyPlugin.dll").
El host busca las exportaciones en su propio directorio raíz, por lo que durante la prueba, compilo toda la solución y copio Plugin.dll desde la carpeta de la biblioteca / clase de Plugin plugin al directorio de depuración del host para que DirectoryCatalog del host lo encuentre y pueda para agregarlo al CompositionContainer. Plugin.dll no se copia automáticamente después de cada reconstrucción, así que lo hago manualmente cada vez que hago cambios en el contrato / implementación.
Sin embargo, un par de veces he ejecutado la aplicación host sin haber copiado (una actualización) Plugin.dll primero, y ha lanzado una excepción durante la composición:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information
Por supuesto, esto se debe al hecho de que el Plugin.dll que está intentando importar desde implementa una versión diferente de IPlugin, donde las firmas de propiedad / método no coinciden. Aunque es fácil evitar esto en un entorno controlado y monitoreado, simplemente evitando (duh) implementaciones de IPlugin obsoletas en la carpeta de complementos, no puedo confiar en tales suposiciones en el entorno de producción, donde se pueden encontrar complementos heredados.
El problema es que esta excepción destruye efectivamente toda la acción de Redactar y no se importan exportaciones. Hubiera preferido que las implementaciones de IPlugin no coincidentes simplemente se ignoren, por lo que otras exportaciones en el (los) catálogo (s), implementando la versión correcta de IPlugin, todavía se importan.
¿Hay alguna manera de lograr esto? Estoy pensando en varias opciones posibles:
- Hay una marca para establecer en el CompositionContainer ("ignorar las importaciones fallidas") antes de o al llamar a Redactar
- Hay una bandera similar para especificar en el atributo
<ImportMany()>
- Hay una manera de "enganchar" al proceso de iteración subyacente en Compose (), y poder tratar cada importación (fallida) individualmente
- Usando la firma fuerte de nombres para buscar de alguna manera solo importaciones que implementan la versión actual de IPlugin
Ideas?
Este problema puede ser causado por varios factores (cualquier excepción en los ensamblados cargados), como dice la excepción, mire el ExceptionLoader para (con suerte) tener alguna idea
Otro problema / solución que encontré es que cuando utilizo DirectoryCatalog , si no especifica el segundo parámetro "searchPattern", MEF cargará TODAS las DLL en esa carpeta (incluido un tercero) y comenzará a buscar tipos de exportación, que pueden También debido a este problema, una solución es tener un nombre de convención en todos los ensamblajes que exportan tipos, y especificar que en el constructor DirectoryCatalog, yo uso * _Plugin.dll, de esa manera MEF solo cargará ensamblajes que contengan tipos exportados
En mi caso, MEF estaba cargando una dll NHibernate y lanzando un error de versión de ensamblaje en la excepción LoaderException (este error puede ocurrir con cualquiera de las dll en el directorio), este enfoque resolvió el problema
También me he encontrado con un problema similar .
Si está seguro de que desea ignorar estos conjuntos "incorrectos", la solución es llamar a AssemblyCatalog.Parts.ToArray() justo después de crear cada catálogo de conjuntos. Esto activará la ReflectionTypeLoadException
que usted menciona. Luego tiene la oportunidad de atrapar la excepción e ignorar el ensamblaje defectuoso.
Cuando haya creado objetos AssemblyCatalog
para todos los conjuntos "buenos", puede agregarlos en un AggregateCatalog
y pasarlo al constructor CompositionContainer
.