c# - registrarse - Manejar ReflectionTypeLoadException durante la composición de MEF
mef cepadem telefono (3)
Estoy utilizando un DirectoryCatalog
en MEF para satisfacer las importaciones en mi aplicación. Sin embargo, a veces hay conjuntos confusos en el directorio que causan una ReflectionTypeLoadException
cuando intento componer el catálogo.
Sé que puedo solucionarlo usando un directorio separado o usando un filtro de búsqueda en el DirectoryCatalog
pero quiero una manera más general de resolver el problema. ¿Hay alguna manera de manejar la excepción y permitir que la composición continúe? ¿O hay otra solución más general?
Estaba haciendo esto desde una API que estaba escribiendo y SafeDirectoryCatalog no registraría varias exportaciones que coincidieran con una sola importación de diferentes ensamblajes. La depuración de MEF se realiza normalmente a través del depurador y TraceListener. Ya usé Log4Net y no quería que alguien tuviera que agregar otra entrada al archivo de configuración solo para admitir el registro. http://blogs.msdn.com/b/dsplaisted/archive/2010/07/13/how-to-debug-and-diagnose-mef-failures.aspx me ocurrió:
// I don''t want people to have to add configuration information to get this logging.
// I know this brittle, but don''t judge... please. It makes consuing the api so much
// easier.
private static void EnsureLog4NetListener()
{
try
{
Assembly compositionAssembly = Assembly.GetAssembly(typeof (CompositionContainer));
Type compSource = compositionAssembly.GetType("System.ComponentModel.Composition.Diagnostics.CompositionTraceSource");
PropertyInfo canWriteErrorProp = compSource.GetProperty("CanWriteError");
canWriteErrorProp.GetGetMethod().Invoke(null,
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static, null, null,
null);
Type traceSourceTraceWriterType =
compositionAssembly.GetType(
"System.ComponentModel.Composition.Diagnostics.TraceSourceTraceWriter");
TraceSource traceSource = (TraceSource)traceSourceTraceWriterType.GetField("Source",
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Static).GetValue(null);
traceSource.Listeners.Add(new Log4NetTraceListener(logger));
}
catch (Exception e)
{
logger.Value.Error("Cannot hook MEF compisition listener. Composition errors may be swallowed.", e);
}
}
Para evitar que otros escriban su propia implementación del SafeDirectoryCatalog, aquí está el que se me ocurrió basado en las sugerencias de Wim Coenen:
public class SafeDirectoryCatalog : ComposablePartCatalog
{
private readonly AggregateCatalog _catalog;
public SafeDirectoryCatalog(string directory)
{
var files = Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories);
_catalog = new AggregateCatalog();
foreach (var file in files)
{
try
{
var asmCat = new AssemblyCatalog(file);
//Force MEF to load the plugin and figure out if there are any exports
// good assemblies will not throw the RTLE exception and can be added to the catalog
if (asmCat.Parts.ToList().Count > 0)
_catalog.Catalogs.Add(asmCat);
}
catch (ReflectionTypeLoadException)
{
}
catch (BadImageFormatException)
{
}
}
}
public override IQueryable<ComposablePartDefinition> Parts
{
get { return _catalog.Parts; }
}
}
DirectoryCatalog
ya tiene código para capturar la ReflectionTypeLoadException
e ignorar esos ensamblados. Desafortunadamente, como he reported , simplemente crear el AssemblyCatalog
aún no activará la excepción, por lo que el código no funciona.
La primera llamada a AssemblyCatalog.Parts
desencadena la excepción.
En lugar de utilizar el DirectoryCatalog
de MEF, tendrá que hacerlo usted mismo:
- escanear un directorio para ensamblajes
- carga cada ensamblaje y crea un
AssemblyCatalog
para ello - invocar
AssemblyCatalog.Parts.ToArray()
para forzar la excepción y atraparla - agregue todos los buenos catálogos con un
AggregateCatalog